mirror of
https://github.com/usmannasir/cyberpanel.git
synced 2026-01-28 18:29:05 +01:00
@@ -537,12 +537,17 @@ def RestartCyberPanel(request):
|
||||
|
||||
def getDashboardStats(request):
|
||||
try:
|
||||
val = request.session['userID']
|
||||
val = request.session.get('userID')
|
||||
if val is None:
|
||||
return HttpResponse(
|
||||
json.dumps({'status': 0, 'error_message': 'Session required'}),
|
||||
content_type='application/json'
|
||||
)
|
||||
currentACL = ACLManager.loadedACL(val)
|
||||
admin = Administrator.objects.get(pk=val)
|
||||
|
||||
# Check if user is admin
|
||||
if currentACL['admin'] == 1:
|
||||
if currentACL.get('admin', 0) == 1:
|
||||
# Admin can see all resources
|
||||
total_users = Administrator.objects.count()
|
||||
total_sites = Websites.objects.count()
|
||||
@@ -580,7 +585,7 @@ def getDashboardStats(request):
|
||||
total_emails = EUsers.objects.filter(emailOwner__domainOwner__domain__in=website_names).count()
|
||||
|
||||
# Count FTP users associated with user's domains
|
||||
total_ftp_users = FTPUsers.objects.filter(domain__in=website_names).count()
|
||||
total_ftp_users = FTPUsers.objects.filter(domain__domain__in=website_names).count()
|
||||
else:
|
||||
total_wp_sites = 0
|
||||
total_dbs = 0
|
||||
@@ -598,18 +603,24 @@ def getDashboardStats(request):
|
||||
}
|
||||
return HttpResponse(json.dumps(data), content_type='application/json')
|
||||
except Exception as e:
|
||||
return HttpResponse(json.dumps({'status': 0, 'error_message': str(e)}), content_type='application/json')
|
||||
logging.writeToFile('getDashboardStats error: %s' % str(e))
|
||||
return HttpResponse(
|
||||
json.dumps({'status': 0, 'error_message': 'Failed to load dashboard stats'}),
|
||||
content_type='application/json'
|
||||
)
|
||||
|
||||
def getTrafficStats(request):
|
||||
try:
|
||||
val = request.session['userID']
|
||||
val = request.session.get('userID')
|
||||
if val is None:
|
||||
return HttpResponse(
|
||||
json.dumps({'status': 0, 'error_message': 'Session required'}),
|
||||
content_type='application/json'
|
||||
)
|
||||
currentACL = ACLManager.loadedACL(val)
|
||||
|
||||
# Only admins should see system-wide network stats
|
||||
if not currentACL.get('admin', 0):
|
||||
return HttpResponse(json.dumps({'status': 0, 'error_message': 'Admin access required', 'admin_only': True}), content_type='application/json')
|
||||
|
||||
# Get network stats from /proc/net/dev (Linux)
|
||||
rx = tx = 0
|
||||
with open('/proc/net/dev', 'r') as f:
|
||||
for line in f.readlines():
|
||||
@@ -617,42 +628,49 @@ def getTrafficStats(request):
|
||||
continue
|
||||
if ':' in line:
|
||||
parts = line.split()
|
||||
rx += int(parts[1])
|
||||
tx += int(parts[9])
|
||||
data = {
|
||||
'rx_bytes': rx,
|
||||
'tx_bytes': tx,
|
||||
'status': 1
|
||||
}
|
||||
try:
|
||||
if len(parts) >= 10:
|
||||
rx += int(parts[1])
|
||||
tx += int(parts[9])
|
||||
except (ValueError, IndexError):
|
||||
continue
|
||||
data = {'rx_bytes': rx, 'tx_bytes': tx, 'status': 1}
|
||||
return HttpResponse(json.dumps(data), content_type='application/json')
|
||||
except Exception as e:
|
||||
return HttpResponse(json.dumps({'status': 0, 'error_message': str(e)}), content_type='application/json')
|
||||
logging.writeToFile('getTrafficStats error: %s' % str(e))
|
||||
return HttpResponse(
|
||||
json.dumps({'status': 0, 'error_message': 'Failed to load traffic stats'}),
|
||||
content_type='application/json'
|
||||
)
|
||||
|
||||
def getDiskIOStats(request):
|
||||
try:
|
||||
val = request.session['userID']
|
||||
val = request.session.get('userID')
|
||||
if val is None:
|
||||
return HttpResponse(
|
||||
json.dumps({'status': 0, 'error_message': 'Session required'}),
|
||||
content_type='application/json'
|
||||
)
|
||||
currentACL = ACLManager.loadedACL(val)
|
||||
|
||||
# Only admins should see system-wide disk I/O stats
|
||||
if not currentACL.get('admin', 0):
|
||||
return HttpResponse(json.dumps({'status': 0, 'error_message': 'Admin access required', 'admin_only': True}), content_type='application/json')
|
||||
|
||||
# Parse /proc/diskstats for all disks
|
||||
read_sectors = 0
|
||||
write_sectors = 0
|
||||
sector_size = 512 # Most Linux systems use 512 bytes per sector
|
||||
sector_size = 512
|
||||
with open('/proc/diskstats', 'r') as f:
|
||||
for line in f:
|
||||
parts = line.split()
|
||||
if len(parts) < 14:
|
||||
continue
|
||||
# parts[2] is device name, skip loopback/ram devices
|
||||
dev = parts[2]
|
||||
if dev.startswith('loop') or dev.startswith('ram'):
|
||||
continue
|
||||
# 6th and 10th columns: sectors read/written
|
||||
read_sectors += int(parts[5])
|
||||
write_sectors += int(parts[9])
|
||||
try:
|
||||
read_sectors += int(parts[5])
|
||||
write_sectors += int(parts[9])
|
||||
except (ValueError, IndexError):
|
||||
continue
|
||||
data = {
|
||||
'read_bytes': read_sectors * sector_size,
|
||||
'write_bytes': write_sectors * sector_size,
|
||||
@@ -660,34 +678,42 @@ def getDiskIOStats(request):
|
||||
}
|
||||
return HttpResponse(json.dumps(data), content_type='application/json')
|
||||
except Exception as e:
|
||||
return HttpResponse(json.dumps({'status': 0, 'error_message': str(e)}), content_type='application/json')
|
||||
logging.writeToFile('getDiskIOStats error: %s' % str(e))
|
||||
return HttpResponse(
|
||||
json.dumps({'status': 0, 'error_message': 'Failed to load disk I/O stats'}),
|
||||
content_type='application/json'
|
||||
)
|
||||
|
||||
def getCPULoadGraph(request):
|
||||
try:
|
||||
val = request.session['userID']
|
||||
val = request.session.get('userID')
|
||||
if val is None:
|
||||
return HttpResponse(
|
||||
json.dumps({'status': 0, 'error_message': 'Session required'}),
|
||||
content_type='application/json'
|
||||
)
|
||||
currentACL = ACLManager.loadedACL(val)
|
||||
|
||||
# Only admins should see system-wide CPU stats
|
||||
if not currentACL.get('admin', 0):
|
||||
return HttpResponse(json.dumps({'status': 0, 'error_message': 'Admin access required', 'admin_only': True}), content_type='application/json')
|
||||
|
||||
# Parse /proc/stat for the 'cpu' line
|
||||
cpu_times = []
|
||||
with open('/proc/stat', 'r') as f:
|
||||
for line in f:
|
||||
if line.startswith('cpu '):
|
||||
parts = line.strip().split()
|
||||
# parts[1:] are user, nice, system, idle, iowait, irq, softirq, steal, guest, guest_nice
|
||||
cpu_times = [float(x) for x in parts[1:]]
|
||||
try:
|
||||
cpu_times = [float(x) for x in parts[1:]]
|
||||
except (ValueError, IndexError):
|
||||
pass
|
||||
break
|
||||
else:
|
||||
cpu_times = []
|
||||
data = {
|
||||
'cpu_times': cpu_times,
|
||||
'status': 1
|
||||
}
|
||||
data = {'cpu_times': cpu_times, 'status': 1}
|
||||
return HttpResponse(json.dumps(data), content_type='application/json')
|
||||
except Exception as e:
|
||||
return HttpResponse(json.dumps({'status': 0, 'error_message': str(e)}), content_type='application/json')
|
||||
logging.writeToFile('getCPULoadGraph error: %s' % str(e))
|
||||
return HttpResponse(
|
||||
json.dumps({'status': 0, 'error_message': 'Failed to load CPU stats'}),
|
||||
content_type='application/json'
|
||||
)
|
||||
|
||||
@csrf_exempt
|
||||
@require_GET
|
||||
|
||||
210
install.sh
210
install.sh
@@ -4,10 +4,141 @@
|
||||
# This installer uses modules for better organization and maintainability
|
||||
# Each module is kept under 500 lines for easy management
|
||||
|
||||
# Note: We use 'set -e' carefully - some operations need to handle failures gracefully
|
||||
set -e
|
||||
|
||||
# Get script directory
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
|
||||
# Early logging function (before main functions are defined)
|
||||
early_log() {
|
||||
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1"
|
||||
}
|
||||
|
||||
# Check if script is being executed via curl/wget (SCRIPT_DIR will be /dev/fd/...)
|
||||
# In that case, we need to clone the repository first
|
||||
if [[ "$SCRIPT_DIR" == /dev/fd/* ]] || [[ ! -d "$SCRIPT_DIR/modules" ]]; then
|
||||
# Script is being executed via curl/wget, need to clone repo first
|
||||
early_log "📥 Detected curl/wget execution - cloning repository..."
|
||||
|
||||
# Determine branch from arguments or use default
|
||||
BRANCH_NAME="v2.5.5-dev"
|
||||
ARGS=("$@")
|
||||
for i in "${!ARGS[@]}"; do
|
||||
if [[ "${ARGS[i]}" == "-b" ]] || [[ "${ARGS[i]}" == "--branch" ]]; then
|
||||
if [[ -n "${ARGS[i+1]}" ]]; then
|
||||
BRANCH_NAME="${ARGS[i+1]}"
|
||||
fi
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
# Clone repository to temporary directory
|
||||
# Try multiple locations if /tmp is full
|
||||
TEMP_DIR=""
|
||||
early_log "Checking available disk space..."
|
||||
|
||||
# Try to clean up old temp directories first
|
||||
rm -rf /tmp/cyberpanel-installer-* 2>/dev/null || true
|
||||
rm -rf /var/tmp/cyberpanel-installer-* 2>/dev/null || true
|
||||
|
||||
# Try multiple temp locations (disable set -e for this section)
|
||||
set +e
|
||||
for temp_location in "/tmp/cyberpanel-installer-$$" "/var/tmp/cyberpanel-installer-$$" "$HOME/cyberpanel-installer-$$" "/root/cyberpanel-installer-$$"; do
|
||||
if mkdir -p "$temp_location" 2>/dev/null; then
|
||||
TEMP_DIR="$temp_location"
|
||||
early_log "Using temporary directory: $TEMP_DIR"
|
||||
break
|
||||
fi
|
||||
done
|
||||
set -e
|
||||
|
||||
# If we still don't have a temp dir, skip git clone and use fallback
|
||||
if [ -z "$TEMP_DIR" ]; then
|
||||
early_log "⚠️ Cannot create temporary directory (disk may be full)"
|
||||
early_log "Skipping git clone, using fallback installer directly..."
|
||||
# Skip to fallback installer
|
||||
TEMP_DIR=""
|
||||
fi
|
||||
|
||||
# Only attempt git clone if we have a temp directory
|
||||
if [ -n "$TEMP_DIR" ]; then
|
||||
early_log "📦 Cloning CyberPanel repository (branch: $BRANCH_NAME)..."
|
||||
early_log "This may take a minute depending on your connection speed..."
|
||||
|
||||
# Try git clone with timeout and better error handling
|
||||
GIT_CLONE_SUCCESS=false
|
||||
|
||||
if command -v timeout >/dev/null 2>&1; then
|
||||
if timeout 180 git clone --depth 1 --branch "$BRANCH_NAME" https://github.com/master3395/cyberpanel.git "$TEMP_DIR/cyberpanel" >/tmp/git-clone.log 2>&1; then
|
||||
GIT_CLONE_SUCCESS=true
|
||||
fi
|
||||
else
|
||||
# No timeout command, try without timeout
|
||||
if git clone --depth 1 --branch "$BRANCH_NAME" https://github.com/master3395/cyberpanel.git "$TEMP_DIR/cyberpanel" >/tmp/git-clone.log 2>&1; then
|
||||
GIT_CLONE_SUCCESS=true
|
||||
fi
|
||||
fi
|
||||
|
||||
# Verify clone was successful and structure is valid
|
||||
if [ "$GIT_CLONE_SUCCESS" = true ] && [ -d "$TEMP_DIR/cyberpanel" ] && [ -f "$TEMP_DIR/cyberpanel/install.sh" ] && [ -d "$TEMP_DIR/cyberpanel/modules" ]; then
|
||||
SCRIPT_DIR="$TEMP_DIR/cyberpanel"
|
||||
cd "$SCRIPT_DIR"
|
||||
early_log "✅ Repository cloned successfully"
|
||||
else
|
||||
# Git clone failed or structure invalid, use fallback
|
||||
GIT_ERROR=$(tail -3 /tmp/git-clone.log 2>/dev/null | tr '\n' ' ')
|
||||
early_log "⚠️ Git clone failed or incomplete"
|
||||
if [ -n "$GIT_ERROR" ]; then
|
||||
early_log "Last error: $GIT_ERROR"
|
||||
fi
|
||||
early_log "Falling back to legacy installer..."
|
||||
rm -rf "$TEMP_DIR/cyberpanel" 2>/dev/null || true
|
||||
TEMP_DIR="" # Clear TEMP_DIR to trigger fallback
|
||||
fi
|
||||
fi
|
||||
|
||||
# If git clone failed or we couldn't create temp dir, use fallback
|
||||
if [ -z "$TEMP_DIR" ] || [ ! -d "$TEMP_DIR/cyberpanel" ] || [ ! -f "$TEMP_DIR/cyberpanel/install.sh" ]; then
|
||||
# Fallback: try to download install.sh from the old method
|
||||
early_log "Using fallback installer method..."
|
||||
OUTPUT=$(cat /etc/*release 2>/dev/null || echo "")
|
||||
if echo "$OUTPUT" | grep -qE "(CentOS|AlmaLinux|CloudLinux|Rocky)" ; then
|
||||
SERVER_OS="CentOS8"
|
||||
yum install -y -q curl wget 2>/dev/null || dnf install -y -q curl wget 2>/dev/null || true
|
||||
elif echo "$OUTPUT" | grep -qE "Ubuntu" ; then
|
||||
SERVER_OS="Ubuntu"
|
||||
apt install -y -qq wget curl 2>/dev/null || true
|
||||
else
|
||||
early_log "❌ Unable to detect OS for fallback installer"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Try multiple locations for fallback script
|
||||
FALLBACK_SCRIPT=""
|
||||
for fallback_location in "/tmp/cyberpanel.sh" "/var/tmp/cyberpanel.sh" "$HOME/cyberpanel.sh"; do
|
||||
rm -f "$fallback_location" 2>/dev/null || true
|
||||
if curl --silent -o "$fallback_location" "https://cyberpanel.sh/?dl&$SERVER_OS" 2>/dev/null || \
|
||||
wget -q -O "$fallback_location" "https://cyberpanel.sh/?dl&$SERVER_OS" 2>/dev/null; then
|
||||
if [ -f "$fallback_location" ]; then
|
||||
FALLBACK_SCRIPT="$fallback_location"
|
||||
chmod +x "$FALLBACK_SCRIPT"
|
||||
break
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
if [ -n "$FALLBACK_SCRIPT" ] && [ -f "$FALLBACK_SCRIPT" ]; then
|
||||
early_log "✅ Fallback installer downloaded, executing..."
|
||||
exec "$FALLBACK_SCRIPT" "$@"
|
||||
else
|
||||
early_log "❌ Failed to download fallback installer"
|
||||
early_log "Please free up disk space or check your internet connection"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
fi # Close the if [[ "$SCRIPT_DIR" == /dev/fd/* ]] block
|
||||
|
||||
MODULES_DIR="$SCRIPT_DIR/modules"
|
||||
|
||||
# Colors for output
|
||||
@@ -88,11 +219,22 @@ detect_operating_system() {
|
||||
print_status "$BLUE" "🔍 Detecting operating system..."
|
||||
|
||||
if detect_os; then
|
||||
# Get OS information
|
||||
# Get OS information using get_os_info() to ensure we capture the values
|
||||
# This outputs variable assignments that we can eval
|
||||
eval $(get_os_info)
|
||||
|
||||
# Export them to ensure they're available to all functions
|
||||
export SERVER_OS OS_FAMILY PACKAGE_MANAGER ARCHITECTURE
|
||||
|
||||
print_status "$GREEN" "✅ OS detected: $SERVER_OS ($OS_FAMILY)"
|
||||
print_status "$GREEN" "✅ Package manager: $PACKAGE_MANAGER"
|
||||
print_status "$GREEN" "✅ Architecture: $ARCHITECTURE"
|
||||
|
||||
# Verify variables are set
|
||||
if [ -z "$SERVER_OS" ] || [ -z "$OS_FAMILY" ] || [ -z "$PACKAGE_MANAGER" ]; then
|
||||
print_status "$RED" "❌ OS variables not properly set after detection"
|
||||
return 1
|
||||
fi
|
||||
return 0
|
||||
else
|
||||
print_status "$RED" "❌ Failed to detect operating system"
|
||||
@@ -104,6 +246,31 @@ detect_operating_system() {
|
||||
install_dependencies() {
|
||||
print_status "$BLUE" "📦 Installing dependencies..."
|
||||
|
||||
# Debug: Show current variable values
|
||||
print_status "$YELLOW" "DEBUG: SERVER_OS='$SERVER_OS', OS_FAMILY='$OS_FAMILY', PACKAGE_MANAGER='$PACKAGE_MANAGER'"
|
||||
|
||||
# Ensure variables are set (they should be from detect_operating_system)
|
||||
if [ -z "$SERVER_OS" ] || [ -z "$OS_FAMILY" ] || [ -z "$PACKAGE_MANAGER" ]; then
|
||||
print_status "$YELLOW" "⚠️ OS variables not set, re-detecting..."
|
||||
# Try to get them again
|
||||
if detect_os; then
|
||||
# Variables should be set by detect_os() in the sourced module
|
||||
export SERVER_OS OS_FAMILY PACKAGE_MANAGER ARCHITECTURE
|
||||
print_status "$GREEN" "✅ Re-detected: SERVER_OS=$SERVER_OS, OS_FAMILY=$OS_FAMILY, PACKAGE_MANAGER=$PACKAGE_MANAGER"
|
||||
else
|
||||
print_status "$RED" "❌ Failed to detect OS for dependency installation"
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Verify variables one more time before calling
|
||||
if [ -z "$SERVER_OS" ] || [ -z "$OS_FAMILY" ] || [ -z "$PACKAGE_MANAGER" ]; then
|
||||
print_status "$RED" "❌ OS variables still not set after re-detection"
|
||||
return 1
|
||||
fi
|
||||
|
||||
print_status "$BLUE" "Calling manage_dependencies with: SERVER_OS='$SERVER_OS', OS_FAMILY='$OS_FAMILY', PACKAGE_MANAGER='$PACKAGE_MANAGER'"
|
||||
|
||||
if manage_dependencies "$SERVER_OS" "$OS_FAMILY" "$PACKAGE_MANAGER"; then
|
||||
print_status "$GREEN" "✅ Dependencies installed successfully"
|
||||
return 0
|
||||
@@ -214,6 +381,42 @@ parse_arguments() {
|
||||
done
|
||||
}
|
||||
|
||||
# Function to check disk space
|
||||
check_disk_space() {
|
||||
local required_gb=10 # Minimum 10GB required
|
||||
local root_available_gb=0
|
||||
|
||||
# Get available space on root filesystem
|
||||
if command -v df >/dev/null 2>&1; then
|
||||
root_available_gb=$(df -BG / | awk 'NR==2 {print $4}' | sed 's/G//' | cut -d. -f1)
|
||||
if [ -z "$root_available_gb" ] || [ "$root_available_gb" = "" ]; then
|
||||
# Try alternative method
|
||||
root_available_gb=$(df -BG / | tail -1 | awk '{print $4}' | sed 's/G//' | cut -d. -f1)
|
||||
fi
|
||||
fi
|
||||
|
||||
# If we couldn't get the value, try without -BG flag
|
||||
if [ -z "$root_available_gb" ] || ! [[ "$root_available_gb" =~ ^[0-9]+$ ]]; then
|
||||
root_available_gb=$(df / | awk 'NR==2 {print $4}' | awk '{printf "%.0f", $1/1024/1024}')
|
||||
fi
|
||||
|
||||
print_status "$BLUE" "💾 Checking disk space..."
|
||||
print_status "$BLUE" " Required: ${required_gb}GB minimum"
|
||||
|
||||
if [[ "$root_available_gb" =~ ^[0-9]+$ ]] && [ "$root_available_gb" -ge "$required_gb" ]; then
|
||||
print_status "$GREEN" " Available: ${root_available_gb}GB (✅ Sufficient)"
|
||||
return 0
|
||||
elif [[ "$root_available_gb" =~ ^[0-9]+$ ]]; then
|
||||
print_status "$YELLOW" " Available: ${root_available_gb}GB (⚠️ Less than ${required_gb}GB recommended)"
|
||||
print_status "$YELLOW" " Installation may fail if disk space runs out"
|
||||
return 1
|
||||
else
|
||||
print_status "$YELLOW" " Could not determine available disk space"
|
||||
print_status "$YELLOW" " Please ensure at least ${required_gb}GB is available"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Main installation function
|
||||
main() {
|
||||
# Initialize log file
|
||||
@@ -223,6 +426,9 @@ main() {
|
||||
print_status "$BLUE" "🚀 Enhanced CyberPanel Installer Starting..."
|
||||
print_status "$BLUE" "Log file: /var/log/cyberpanel_install.log"
|
||||
|
||||
# Check disk space before proceeding
|
||||
check_disk_space
|
||||
|
||||
# Parse command line arguments
|
||||
parse_arguments "$@"
|
||||
|
||||
@@ -251,4 +457,4 @@ main() {
|
||||
}
|
||||
|
||||
# Run main function
|
||||
main "$@"
|
||||
main "$@"
|
||||
|
||||
@@ -1451,9 +1451,189 @@ module cyberpanel_ols {
|
||||
except:
|
||||
return False
|
||||
|
||||
def checkExistingMariaDB(self):
|
||||
"""Check if MariaDB/MySQL is already installed and return version info"""
|
||||
try:
|
||||
# Check if MariaDB/MySQL server package is installed
|
||||
if self.distro == ubuntu:
|
||||
command = 'dpkg -l | grep -iE "^(ii|rc).*mariadb-server|mysql-server" 2>/dev/null || echo ""'
|
||||
else:
|
||||
command = 'rpm -qa | grep -iE "^(mariadb-server|mysql-server|MariaDB-server)" 2>/dev/null || echo ""'
|
||||
|
||||
result = subprocess.run(command, shell=True, capture_output=True, universal_newlines=True)
|
||||
|
||||
if result.stdout.strip():
|
||||
# MariaDB/MySQL server package is installed, get version
|
||||
version_command = 'mysql --version 2>/dev/null || mariadb --version 2>/dev/null || echo ""'
|
||||
version_result = subprocess.run(version_command, shell=True, capture_output=True, universal_newlines=True)
|
||||
version_output = version_result.stdout.strip()
|
||||
|
||||
if version_output:
|
||||
# Extract version number (e.g., "10.11.15" from "mysql Ver 10.11.15-MariaDB")
|
||||
import re
|
||||
version_match = re.search(r'(\d+\.\d+\.\d+)', version_output)
|
||||
if version_match:
|
||||
installed_version = version_match.group(1)
|
||||
major_minor = '.'.join(installed_version.split('.')[:2]) # e.g., "10.11"
|
||||
logging.InstallLog.writeToFile(f"Found existing MariaDB installation: {installed_version} (major.minor: {major_minor})")
|
||||
return True, installed_version, major_minor
|
||||
|
||||
logging.InstallLog.writeToFile("Found MariaDB/MySQL package but could not determine version")
|
||||
return True, "unknown", "unknown"
|
||||
|
||||
# Also check if MariaDB service exists and data directory exists (might be installed but package query failed)
|
||||
if os.path.exists('/var/lib/mysql') and os.listdir('/var/lib/mysql'):
|
||||
logging.InstallLog.writeToFile("Found MariaDB data directory, assuming MariaDB is installed")
|
||||
# Try to get version one more time
|
||||
version_command = 'mysql --version 2>/dev/null || mariadb --version 2>/dev/null || echo ""'
|
||||
version_result = subprocess.run(version_command, shell=True, capture_output=True, universal_newlines=True)
|
||||
version_output = version_result.stdout.strip()
|
||||
if version_output:
|
||||
import re
|
||||
version_match = re.search(r'(\d+\.\d+\.\d+)', version_output)
|
||||
if version_match:
|
||||
installed_version = version_match.group(1)
|
||||
major_minor = '.'.join(installed_version.split('.')[:2])
|
||||
return True, installed_version, major_minor
|
||||
return True, "unknown", "unknown"
|
||||
|
||||
return False, None, None
|
||||
except Exception as e:
|
||||
logging.InstallLog.writeToFile(f"Error checking existing MariaDB: {str(e)}")
|
||||
return False, None, None
|
||||
|
||||
def _attemptMariaDBUpgrade(self):
|
||||
"""Attempt to upgrade MariaDB to 12.1. Returns True if successful, False otherwise."""
|
||||
try:
|
||||
if self.distro == ubuntu:
|
||||
# Ubuntu MariaDB upgrade
|
||||
command = 'DEBIAN_FRONTEND=noninteractive apt-get install software-properties-common apt-transport-https curl -y'
|
||||
result = subprocess.run(command, shell=True, capture_output=True, universal_newlines=True)
|
||||
if result.returncode != 0:
|
||||
logging.InstallLog.writeToFile(f"Failed to install prerequisites: {result.stderr}")
|
||||
return False
|
||||
|
||||
command = "mkdir -p /etc/apt/keyrings"
|
||||
subprocess.run(command, shell=True, check=False)
|
||||
|
||||
command = "curl -o /etc/apt/keyrings/mariadb-keyring.pgp 'https://mariadb.org/mariadb_release_signing_key.pgp'"
|
||||
result = subprocess.run(command, shell=True, capture_output=True, universal_newlines=True)
|
||||
if result.returncode != 0:
|
||||
logging.InstallLog.writeToFile(f"Failed to download MariaDB keyring: {result.stderr}")
|
||||
return False
|
||||
|
||||
# Setup MariaDB 12.1 repository
|
||||
command = 'curl -LsS https://downloads.mariadb.com/MariaDB/mariadb_repo_setup | sudo bash -s -- --mariadb-server-version=12.1'
|
||||
result = subprocess.run(command, shell=True, capture_output=True, universal_newlines=True)
|
||||
if result.returncode != 0:
|
||||
logging.InstallLog.writeToFile(f"Failed to setup MariaDB repository: {result.stderr}")
|
||||
return False
|
||||
|
||||
command = 'DEBIAN_FRONTEND=noninteractive apt-get update -y'
|
||||
result = subprocess.run(command, shell=True, capture_output=True, universal_newlines=True)
|
||||
if result.returncode != 0:
|
||||
logging.InstallLog.writeToFile(f"Failed to update package list: {result.stderr}")
|
||||
return False
|
||||
|
||||
# Attempt to install MariaDB 12.1
|
||||
command = "DEBIAN_FRONTEND=noninteractive apt-get install mariadb-server -y"
|
||||
result = subprocess.run(command, shell=True, capture_output=True, universal_newlines=True)
|
||||
if result.returncode != 0:
|
||||
# Check if error is due to upgrade restrictions
|
||||
error_output = result.stderr + result.stdout
|
||||
if "upgrade" in error_output.lower() or "manual" in error_output.lower():
|
||||
logging.InstallLog.writeToFile("MariaDB upgrade blocked - requires manual intervention")
|
||||
else:
|
||||
logging.InstallLog.writeToFile(f"MariaDB installation failed: {error_output}")
|
||||
return False
|
||||
|
||||
return True
|
||||
else:
|
||||
# RHEL-based MariaDB upgrade
|
||||
# Setup MariaDB 12.1 repository
|
||||
command = 'curl -LsS https://downloads.mariadb.com/MariaDB/mariadb_repo_setup | sudo bash -s -- --mariadb-server-version=12.1'
|
||||
result = subprocess.run(command, shell=True, capture_output=True, universal_newlines=True)
|
||||
if result.returncode != 0:
|
||||
logging.InstallLog.writeToFile(f"Failed to setup MariaDB repository: {result.stderr}")
|
||||
return False
|
||||
|
||||
# Attempt to install MariaDB 12.1
|
||||
# Use --allowerasing to allow package replacements if needed
|
||||
command = 'dnf install mariadb-server mariadb-devel mariadb-client-utils -y --allowerasing'
|
||||
result = subprocess.run(command, shell=True, capture_output=True, universal_newlines=True)
|
||||
if result.returncode != 0:
|
||||
# Check if error is due to upgrade restrictions
|
||||
error_output = result.stderr + result.stdout
|
||||
if "PREIN scriptlet failed" in error_output or "upgrade" in error_output.lower() or "manual" in error_output.lower():
|
||||
logging.InstallLog.writeToFile("MariaDB upgrade blocked by package manager - requires manual intervention")
|
||||
else:
|
||||
logging.InstallLog.writeToFile(f"MariaDB installation failed: {error_output}")
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
logging.InstallLog.writeToFile(f"Exception during MariaDB upgrade attempt: {str(e)}")
|
||||
return False
|
||||
|
||||
def installMySQL(self, mysql):
|
||||
"""Install MySQL/MariaDB"""
|
||||
try:
|
||||
# Check if MariaDB is already installed
|
||||
is_installed, installed_version, major_minor = self.checkExistingMariaDB()
|
||||
|
||||
if is_installed:
|
||||
self.stdOut(f"MariaDB/MySQL is already installed (version: {installed_version})", 1)
|
||||
|
||||
# Check if we need to upgrade
|
||||
should_try_upgrade = False
|
||||
if major_minor and major_minor != "unknown":
|
||||
try:
|
||||
major_ver = float(major_minor)
|
||||
if major_ver < 12.0:
|
||||
should_try_upgrade = True
|
||||
self.stdOut(f"Existing MariaDB {major_minor} detected. Attempting to upgrade to MariaDB 12.1...", 1)
|
||||
self.stdOut("If upgrade fails, we will use the existing MariaDB installation.", 1)
|
||||
except (ValueError, TypeError):
|
||||
pass
|
||||
|
||||
# If MariaDB 10.x is installed, try to upgrade to 12.1 first
|
||||
if should_try_upgrade:
|
||||
try:
|
||||
self.stdOut("Attempting to install MariaDB 12.1...", 1)
|
||||
upgrade_success = self._attemptMariaDBUpgrade()
|
||||
if upgrade_success:
|
||||
self.stdOut("✅ Successfully upgraded to MariaDB 12.1", 1)
|
||||
self.startMariaDB()
|
||||
self.changeMYSQLRootPassword()
|
||||
self.fixMariaDB()
|
||||
return True
|
||||
else:
|
||||
self.stdOut("⚠️ MariaDB 12.1 upgrade failed, using existing MariaDB installation", 1)
|
||||
self.startMariaDB()
|
||||
return True
|
||||
except Exception as upgrade_error:
|
||||
error_msg = str(upgrade_error)
|
||||
logging.InstallLog.writeToFile(f"MariaDB upgrade attempt failed: {error_msg}")
|
||||
|
||||
# Check if error is due to upgrade restrictions
|
||||
if "PREIN scriptlet failed" in error_msg or "upgrade" in error_msg.lower() or "manual" in error_msg.lower():
|
||||
self.stdOut("⚠️ MariaDB upgrade blocked by package manager (10.x to 12.x requires manual upgrade)", 1)
|
||||
self.stdOut(f"Using existing MariaDB {installed_version} installation", 1)
|
||||
else:
|
||||
self.stdOut(f"⚠️ MariaDB upgrade failed: {error_msg}", 1)
|
||||
self.stdOut(f"Using existing MariaDB {installed_version} installation", 1)
|
||||
|
||||
# Fall back to existing installation
|
||||
self.startMariaDB()
|
||||
return True
|
||||
|
||||
# MariaDB 12.x or higher already installed, or version unknown but working
|
||||
# Just ensure it's running
|
||||
self.stdOut("Using existing MariaDB installation", 1)
|
||||
self.startMariaDB()
|
||||
return True
|
||||
|
||||
self.stdOut("Installing MySQL/MariaDB...", 1)
|
||||
|
||||
if self.distro == ubuntu:
|
||||
|
||||
Reference in New Issue
Block a user