mirror of
https://github.com/usmannasir/cyberpanel.git
synced 2026-02-04 13:49:04 +01:00
- Added new model `CatchAllEmail` to store catch-all email configurations per domain. - Implemented views for fetching, saving, and deleting catch-all email configurations, enhancing email management capabilities. - Updated URL routing to include endpoints for catch-all email operations. - Enhanced error handling and permission checks for email forwarding actions. These changes improve the flexibility and user experience of email management within CyberPanel.
6666 lines
288 KiB
Python
6666 lines
288 KiB
Python
import json
|
|
import os
|
|
import os.path
|
|
import sys
|
|
import argparse
|
|
import pwd
|
|
import grp
|
|
import re
|
|
|
|
sys.path.append('/usr/local/CyberCP')
|
|
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "CyberCP.settings")
|
|
from plogical.errorSanitizer import ErrorSanitizer
|
|
import shlex
|
|
import subprocess
|
|
import shutil
|
|
import time
|
|
import MySQLdb as mysql
|
|
import random
|
|
import string
|
|
|
|
def update_all_config_files_with_password(new_password):
|
|
"""
|
|
Update all configuration files that use the cyberpanel database password.
|
|
This includes FTP, PowerDNS, Postfix, Dovecot configurations.
|
|
"""
|
|
config_updates = [
|
|
# Django settings
|
|
{
|
|
'path': '/usr/local/CyberCP/CyberCP/settings.py',
|
|
'updates': [
|
|
(r"('cyberpanel'[^}]+?'PASSWORD':\s*')[^']+'", r"\1%s'" % new_password)
|
|
]
|
|
},
|
|
# FTP configurations
|
|
{
|
|
'path': '/etc/pure-ftpd/pureftpd-mysql.conf',
|
|
'updates': [
|
|
(r'^MYSQLPassword\s+.*$', 'MYSQLPassword %s' % new_password)
|
|
]
|
|
},
|
|
{
|
|
'path': '/etc/pure-ftpd/db/mysql.conf', # Ubuntu specific
|
|
'updates': [
|
|
(r'^MYSQLPassword\s+.*$', 'MYSQLPassword %s' % new_password)
|
|
]
|
|
},
|
|
# PowerDNS configurations
|
|
{
|
|
'path': '/etc/pdns/pdns.conf', # CentOS/RHEL
|
|
'updates': [
|
|
(r'^gmysql-password=.*$', 'gmysql-password=%s' % new_password)
|
|
]
|
|
},
|
|
{
|
|
'path': '/etc/powerdns/pdns.conf', # Ubuntu/Debian
|
|
'updates': [
|
|
(r'^gmysql-password=.*$', 'gmysql-password=%s' % new_password)
|
|
]
|
|
},
|
|
# Postfix MySQL configurations
|
|
{
|
|
'path': '/etc/postfix/mysql-virtual_domains.cf',
|
|
'updates': [
|
|
(r'^password\s*=.*$', 'password = %s' % new_password)
|
|
]
|
|
},
|
|
{
|
|
'path': '/etc/postfix/mysql-virtual_forwardings.cf',
|
|
'updates': [
|
|
(r'^password\s*=.*$', 'password = %s' % new_password)
|
|
]
|
|
},
|
|
{
|
|
'path': '/etc/postfix/mysql-virtual_mailboxes.cf',
|
|
'updates': [
|
|
(r'^password\s*=.*$', 'password = %s' % new_password)
|
|
]
|
|
},
|
|
{
|
|
'path': '/etc/postfix/mysql-virtual_email2email.cf',
|
|
'updates': [
|
|
(r'^password\s*=.*$', 'password = %s' % new_password)
|
|
]
|
|
},
|
|
# Dovecot MySQL configuration
|
|
{
|
|
'path': '/etc/dovecot/dovecot-sql.conf.ext',
|
|
'updates': [
|
|
(r'^connect\s*=.*$', lambda m: update_dovecot_connect_string(m.group(0), new_password))
|
|
]
|
|
}
|
|
]
|
|
|
|
for config in config_updates:
|
|
if not os.path.exists(config['path']):
|
|
continue
|
|
|
|
try:
|
|
with open(config['path'], 'r') as f:
|
|
content = f.read()
|
|
|
|
original_content = content
|
|
for pattern, replacement in config['updates']:
|
|
if callable(replacement):
|
|
# For complex replacements like dovecot connect string
|
|
content = re.sub(pattern, replacement, content, flags=re.MULTILINE)
|
|
else:
|
|
content = re.sub(pattern, replacement, content, flags=re.MULTILINE)
|
|
|
|
if content != original_content:
|
|
with open(config['path'], 'w') as f:
|
|
f.write(content)
|
|
print("[RECOVERY] Updated password in: %s" % config['path'])
|
|
except Exception as e:
|
|
print("[RECOVERY] Warning: Could not update %s: %s" % (config['path'], str(e)))
|
|
|
|
def update_dovecot_connect_string(connect_line, new_password):
|
|
"""
|
|
Update the password in dovecot's connect string.
|
|
Format: connect = host=localhost dbname=cyberpanel user=cyberpanel password=oldpass
|
|
"""
|
|
# Replace the password part in the connect string
|
|
updated = re.sub(r'password=\S+', 'password=%s' % new_password, connect_line)
|
|
return updated
|
|
|
|
def restart_affected_services():
|
|
"""
|
|
Restart services that use the cyberpanel database password.
|
|
"""
|
|
services_to_restart = [
|
|
'pure-ftpd', # FTP service
|
|
'postfix', # Mail transfer agent
|
|
'dovecot', # IMAP/POP3 server
|
|
'pdns', # PowerDNS (CentOS/RHEL)
|
|
'powerdns', # PowerDNS (Ubuntu/Debian)
|
|
]
|
|
|
|
for service in services_to_restart:
|
|
try:
|
|
# Try systemctl first (systemd)
|
|
result = subprocess.run(['systemctl', 'restart', service],
|
|
capture_output=True, text=True)
|
|
if result.returncode == 0:
|
|
print("[RECOVERY] Restarted service: %s" % service)
|
|
elif 'Unit' in result.stderr and 'not found' in result.stderr:
|
|
# Service doesn't exist, skip
|
|
pass
|
|
else:
|
|
# Try service command (older systems)
|
|
result = subprocess.run(['service', service, 'restart'],
|
|
capture_output=True, text=True)
|
|
if result.returncode == 0:
|
|
print("[RECOVERY] Restarted service: %s" % service)
|
|
except Exception as e:
|
|
print("[RECOVERY] Warning: Could not restart %s: %s" % (service, str(e)))
|
|
|
|
# Try to import settings, but handle case where CyberCP directory is damaged
|
|
try:
|
|
from CyberCP import settings
|
|
except ImportError:
|
|
print("WARNING: Cannot import CyberCP settings. Attempting recovery...")
|
|
|
|
def recover_database_credentials():
|
|
"""Attempt to recover or reset database credentials"""
|
|
|
|
# First, ensure we have root MySQL password
|
|
if not os.path.exists('/etc/cyberpanel/mysqlPassword'):
|
|
print("FATAL: Cannot find MySQL root password file at /etc/cyberpanel/mysqlPassword")
|
|
print("Manual intervention required.")
|
|
sys.exit(1)
|
|
|
|
root_password = open('/etc/cyberpanel/mysqlPassword', 'r').read().strip()
|
|
cyberpanel_password = None
|
|
|
|
# Try to read existing settings.py to get cyberpanel password
|
|
settings_path = '/usr/local/CyberCP/CyberCP/settings.py'
|
|
if os.path.exists(settings_path):
|
|
try:
|
|
with open(settings_path, 'r') as f:
|
|
settings_content = f.read()
|
|
|
|
import re
|
|
# Extract cyberpanel database password
|
|
db_pattern = r"'default':[^}]*'USER':\s*'cyberpanel'[^}]*'PASSWORD':\s*'([^']+)'"
|
|
match = re.search(db_pattern, settings_content, re.DOTALL)
|
|
|
|
if match:
|
|
cyberpanel_password = match.group(1)
|
|
print("Found existing cyberpanel password in settings.py")
|
|
|
|
# Test if this password actually works
|
|
try:
|
|
test_conn = mysql.connect(host='localhost', user='cyberpanel',
|
|
passwd=cyberpanel_password, db='cyberpanel')
|
|
test_conn.close()
|
|
print("Verified cyberpanel database credentials are valid")
|
|
except:
|
|
print("Found password in settings.py but it doesn't work, will reset")
|
|
cyberpanel_password = None
|
|
except Exception as e:
|
|
print("Could not extract password from settings.py: %s" % str(e))
|
|
|
|
# If we couldn't get a working password, we need to reset it
|
|
if cyberpanel_password is None:
|
|
print("Resetting cyberpanel database user password...")
|
|
|
|
# Check if we're on Ubuntu or CentOS
|
|
# On Ubuntu, cyberpanel uses root password; on CentOS, it uses a separate password
|
|
if os.path.exists('/etc/lsb-release'):
|
|
# Ubuntu - use root password
|
|
cyberpanel_password = root_password
|
|
reset_to_root = True
|
|
else:
|
|
# CentOS/others - generate new password
|
|
chars = string.ascii_letters + string.digits
|
|
cyberpanel_password = ''.join(random.choice(chars) for _ in range(14))
|
|
reset_to_root = False
|
|
|
|
try:
|
|
# Connect as root and reset cyberpanel user
|
|
conn = mysql.connect(host='localhost', user='root', passwd=root_password)
|
|
cursor = conn.cursor()
|
|
|
|
# Check if cyberpanel database exists
|
|
cursor.execute("SHOW DATABASES LIKE 'cyberpanel'")
|
|
if not cursor.fetchone():
|
|
print("Creating cyberpanel database...")
|
|
cursor.execute("CREATE DATABASE IF NOT EXISTS cyberpanel")
|
|
|
|
# Reset cyberpanel user - drop and recreate to ensure clean state
|
|
cursor.execute("DROP USER IF EXISTS 'cyberpanel'@'localhost'")
|
|
cursor.execute("CREATE USER 'cyberpanel'@'localhost' IDENTIFIED BY '%s'" % cyberpanel_password)
|
|
cursor.execute("GRANT ALL PRIVILEGES ON cyberpanel.* TO 'cyberpanel'@'localhost'")
|
|
cursor.execute("FLUSH PRIVILEGES")
|
|
|
|
conn.close()
|
|
|
|
if reset_to_root:
|
|
print("Reset cyberpanel user password to match root password (Ubuntu style)")
|
|
else:
|
|
print("Reset cyberpanel user with new generated password (CentOS style)")
|
|
|
|
# Update all configuration files with the new password
|
|
print("Updating all service configuration files with new password...")
|
|
update_all_config_files_with_password(cyberpanel_password)
|
|
|
|
# Restart affected services to pick up new configuration
|
|
print("Restarting affected services...")
|
|
restart_affected_services()
|
|
|
|
# Save the password to a temporary file for the upgrade process
|
|
temp_pass_file = '/tmp/cyberpanel_recovered_password'
|
|
with open(temp_pass_file, 'w') as f:
|
|
f.write(cyberpanel_password)
|
|
os.chmod(temp_pass_file, 0o600)
|
|
print("Saved recovered password to temporary file")
|
|
|
|
except Exception as e:
|
|
print("Failed to reset cyberpanel database user: %s" % str(e))
|
|
print("Manual intervention required. Please run:")
|
|
print(" mysql -u root -p")
|
|
print(" CREATE DATABASE IF NOT EXISTS cyberpanel;")
|
|
print(" GRANT ALL PRIVILEGES ON cyberpanel.* TO 'cyberpanel'@'localhost' IDENTIFIED BY 'your_password';")
|
|
print(" FLUSH PRIVILEGES;")
|
|
sys.exit(1)
|
|
|
|
return cyberpanel_password, root_password
|
|
|
|
# Perform recovery
|
|
cyberpanel_password, root_password = recover_database_credentials()
|
|
|
|
# Create a minimal settings object for recovery
|
|
class MinimalSettings:
|
|
DATABASES = {
|
|
'default': {
|
|
'NAME': 'cyberpanel',
|
|
'USER': 'cyberpanel',
|
|
'PASSWORD': cyberpanel_password,
|
|
'HOST': 'localhost',
|
|
'PORT': '3306'
|
|
},
|
|
'rootdb': {
|
|
'NAME': 'mysql',
|
|
'USER': 'root',
|
|
'PASSWORD': root_password,
|
|
'HOST': 'localhost',
|
|
'PORT': '3306'
|
|
}
|
|
}
|
|
|
|
settings = MinimalSettings()
|
|
print("Recovery complete. Continuing with upgrade...")
|
|
|
|
VERSION = '2.4'
|
|
BUILD = 4
|
|
|
|
CENTOS7 = 0
|
|
CENTOS8 = 1
|
|
Ubuntu18 = 2
|
|
Ubuntu20 = 3
|
|
CloudLinux7 = 4
|
|
CloudLinux8 = 5
|
|
openEuler20 = 6
|
|
openEuler22 = 7
|
|
Ubuntu22 = 8
|
|
Ubuntu24 = 9
|
|
Debian11 = 10
|
|
Debian12 = 11
|
|
Debian13 = 12
|
|
|
|
|
|
class Upgrade:
|
|
logPath = "/usr/local/lscp/logs/upgradeLog"
|
|
cdn = 'cdn.cyberpanel.sh'
|
|
installedOutput = ''
|
|
CentOSPath = '/etc/redhat-release'
|
|
UbuntuPath = '/etc/lsb-release'
|
|
openEulerPath = '/etc/openEuler-release'
|
|
DebianPath = '/etc/os-release'
|
|
FromCloud = 0
|
|
SnappyVersion = '2.38.2'
|
|
LogPathNew = '/home/cyberpanel/upgrade_logs'
|
|
SoftUpgrade = 0
|
|
|
|
AdminACL = '{"adminStatus":1, "versionManagement": 1, "createNewUser": 1, "listUsers": 1, "deleteUser":1 , "resellerCenter": 1, ' \
|
|
'"changeUserACL": 1, "createWebsite": 1, "modifyWebsite": 1, "suspendWebsite": 1, "deleteWebsite": 1, ' \
|
|
'"createPackage": 1, "listPackages": 1, "deletePackage": 1, "modifyPackage": 1, "createDatabase": 1, "deleteDatabase": 1, ' \
|
|
'"listDatabases": 1, "createNameServer": 1, "createDNSZone": 1, "deleteZone": 1, "addDeleteRecords": 1, ' \
|
|
'"createEmail": 1, "listEmails": 1, "deleteEmail": 1, "emailForwarding": 1, "changeEmailPassword": 1, ' \
|
|
'"dkimManager": 1, "createFTPAccount": 1, "deleteFTPAccount": 1, "listFTPAccounts": 1, "createBackup": 1,' \
|
|
' "restoreBackup": 1, "addDeleteDestinations": 1, "scheduleBackups": 1, "remoteBackups": 1, "googleDriveBackups": 1, "manageSSL": 1, ' \
|
|
'"hostnameSSL": 1, "mailServerSSL": 1 }'
|
|
|
|
ResellerACL = '{"adminStatus":0, "versionManagement": 1, "createNewUser": 1, "listUsers": 1, "deleteUser": 1 , "resellerCenter": 1, ' \
|
|
'"changeUserACL": 0, "createWebsite": 1, "modifyWebsite": 1, "suspendWebsite": 1, "deleteWebsite": 1, ' \
|
|
'"createPackage": 1, "listPackages": 1, "deletePackage": 1, "modifyPackage": 1, "createDatabase": 1, "deleteDatabase": 1, ' \
|
|
'"listDatabases": 1, "createNameServer": 1, "createDNSZone": 1, "deleteZone": 1, "addDeleteRecords": 1, ' \
|
|
'"createEmail": 1, "listEmails": 1, "deleteEmail": 1, "emailForwarding": 1, "changeEmailPassword": 1, ' \
|
|
'"dkimManager": 1, "createFTPAccount": 1, "deleteFTPAccount": 1, "listFTPAccounts": 1, "createBackup": 1,' \
|
|
' "restoreBackup": 1, "addDeleteDestinations": 0, "scheduleBackups": 0, "remoteBackups": 0, "googleDriveBackups": 1, "manageSSL": 1, ' \
|
|
'"hostnameSSL": 0, "mailServerSSL": 0 }'
|
|
|
|
UserACL = '{"adminStatus":0, "versionManagement": 1, "createNewUser": 0, "listUsers": 0, "deleteUser": 0 , "resellerCenter": 0, ' \
|
|
'"changeUserACL": 0, "createWebsite": 0, "modifyWebsite": 0, "suspendWebsite": 0, "deleteWebsite": 0, ' \
|
|
'"createPackage": 0, "listPackages": 0, "deletePackage": 0, "modifyPackage": 0, "createDatabase": 1, "deleteDatabase": 1, ' \
|
|
'"listDatabases": 1, "createNameServer": 0, "createDNSZone": 1, "deleteZone": 1, "addDeleteRecords": 1, ' \
|
|
'"createEmail": 1, "listEmails": 1, "deleteEmail": 1, "emailForwarding": 1, "changeEmailPassword": 1, ' \
|
|
'"dkimManager": 1, "createFTPAccount": 1, "deleteFTPAccount": 1, "listFTPAccounts": 1, "createBackup": 1,' \
|
|
' "restoreBackup": 0, "addDeleteDestinations": 0, "scheduleBackups": 0, "remoteBackups": 0, "googleDriveBackups": 1, "manageSSL": 1, ' \
|
|
'"hostnameSSL": 0, "mailServerSSL": 0 }'
|
|
|
|
@staticmethod
|
|
def FetchCloudLinuxAlmaVersionVersion():
|
|
if os.path.exists('/etc/os-release'):
|
|
data = open('/etc/os-release', 'r').read()
|
|
if (data.find('CloudLinux') > -1 or data.find('cloudlinux') > -1) and (
|
|
data.find('8.9') > -1 or data.find('Anatoly Levchenko') > -1 or data.find('VERSION="8.') > -1):
|
|
return 'cl-89'
|
|
elif (data.find('CloudLinux') > -1 or data.find('cloudlinux') > -1) and (
|
|
data.find('8.8') > -1 or data.find('Anatoly Filipchenko') > -1):
|
|
return 'cl-88'
|
|
elif (data.find('CloudLinux') > -1 or data.find('cloudlinux') > -1) and (
|
|
data.find('9.4') > -1 or data.find('VERSION="9.') > -1):
|
|
return 'cl-88'
|
|
elif (data.find('AlmaLinux') > -1 or data.find('almalinux') > -1) and (
|
|
data.find('8.9') > -1 or data.find('Midnight Oncilla') > -1 or data.find('VERSION="8.') > -1):
|
|
return 'al-88'
|
|
elif (data.find('AlmaLinux') > -1 or data.find('almalinux') > -1) and (
|
|
data.find('8.7') > -1 or data.find('Stone Smilodon') > -1):
|
|
return 'al-87'
|
|
elif (data.find('AlmaLinux') > -1 or data.find('almalinux') > -1) and (
|
|
data.find('9.4') > -1 or data.find('9.3') > -1 or data.find('Shamrock Pampas') > -1 or data.find(
|
|
'Seafoam Ocelot') > -1 or data.find('VERSION="9.') > -1):
|
|
return 'al-93'
|
|
return None
|
|
|
|
@staticmethod
|
|
def decideCentosVersion():
|
|
|
|
if open(Upgrade.CentOSPath, 'r').read().find('CentOS Linux release 8') > -1:
|
|
return CENTOS8
|
|
else:
|
|
return CENTOS7
|
|
|
|
@staticmethod
|
|
def FindOperatingSytem():
|
|
|
|
if os.path.exists(Upgrade.CentOSPath):
|
|
result = open(Upgrade.CentOSPath, 'r').read()
|
|
|
|
if result.find('CentOS Linux release 8') > -1 or result.find('CloudLinux release 8') > -1:
|
|
return CENTOS8
|
|
else:
|
|
return CENTOS7
|
|
|
|
elif os.path.exists(Upgrade.openEulerPath):
|
|
result = open(Upgrade.openEulerPath, 'r').read()
|
|
|
|
if result.find('20.03') > -1:
|
|
return openEuler20
|
|
elif result.find('22.03') > -1:
|
|
return openEuler22
|
|
|
|
elif os.path.exists(Upgrade.DebianPath):
|
|
result = open(Upgrade.DebianPath, 'r').read()
|
|
|
|
if result.find('Debian GNU/Linux 11') > -1:
|
|
return Debian11
|
|
elif result.find('Debian GNU/Linux 12') > -1:
|
|
return Debian12
|
|
elif result.find('Debian GNU/Linux 13') > -1:
|
|
return Debian13
|
|
else:
|
|
return Debian11 # Default to Debian 11 for older versions
|
|
|
|
else:
|
|
result = open(Upgrade.UbuntuPath, 'r').read()
|
|
|
|
if result.find('20.04') > -1:
|
|
return Ubuntu20
|
|
elif result.find('22.04') > -1:
|
|
return Ubuntu22
|
|
elif result.find('24.04') > -1:
|
|
return Ubuntu24
|
|
else:
|
|
return Ubuntu18
|
|
|
|
@staticmethod
|
|
def stdOut(message, do_exit=0):
|
|
print("\n\n")
|
|
print(("[" + time.strftime(
|
|
"%m.%d.%Y_%H-%M-%S") + "] #########################################################################\n"))
|
|
print(("[" + time.strftime("%m.%d.%Y_%H-%M-%S") + "] " + message + "\n"))
|
|
print(("[" + time.strftime(
|
|
"%m.%d.%Y_%H-%M-%S") + "] #########################################################################\n"))
|
|
|
|
WriteToFile = open(Upgrade.LogPathNew, 'a')
|
|
WriteToFile.write(("[" + time.strftime(
|
|
"%m.%d.%Y_%H-%M-%S") + "] #########################################################################\n"))
|
|
WriteToFile.write(("[" + time.strftime("%m.%d.%Y_%H-%M-%S") + "] " + message + "\n"))
|
|
WriteToFile.write(("[" + time.strftime(
|
|
"%m.%d.%Y_%H-%M-%S") + "] #########################################################################\n"))
|
|
WriteToFile.close()
|
|
|
|
if do_exit:
|
|
|
|
### remove log file path incase its there
|
|
|
|
if Upgrade.SoftUpgrade:
|
|
time.sleep(10)
|
|
if os.path.exists(Upgrade.LogPathNew):
|
|
os.remove(Upgrade.LogPathNew)
|
|
|
|
if Upgrade.FromCloud == 0:
|
|
os._exit(0)
|
|
|
|
@staticmethod
|
|
def executioner(command, component, do_exit=0, shell=False):
|
|
try:
|
|
FNULL = open(os.devnull, 'w')
|
|
count = 0
|
|
while True:
|
|
if shell == False:
|
|
res = subprocess.call(shlex.split(command), stderr=subprocess.STDOUT)
|
|
else:
|
|
res = subprocess.call(command, stderr=subprocess.STDOUT, shell=True)
|
|
if res != 0:
|
|
count = count + 1
|
|
Upgrade.stdOut(component + ' failed, trying again, try number: ' + str(count), 0)
|
|
if count == 3:
|
|
Upgrade.stdOut(component + ' failed.', do_exit)
|
|
return False
|
|
else:
|
|
Upgrade.stdOut(component + ' successful.', 0)
|
|
break
|
|
return True
|
|
except:
|
|
return False
|
|
|
|
@staticmethod
|
|
def executioner_silent(command, component, do_exit=0, shell=False):
|
|
"""Silent version of executioner that suppresses all output"""
|
|
try:
|
|
FNULL = open(os.devnull, 'w')
|
|
count = 0
|
|
while True:
|
|
if shell == False:
|
|
res = subprocess.call(shlex.split(command), stdout=FNULL, stderr=FNULL)
|
|
else:
|
|
res = subprocess.call(command, stdout=FNULL, stderr=FNULL, shell=True)
|
|
if res != 0:
|
|
count = count + 1
|
|
if count == 3:
|
|
FNULL.close()
|
|
return False
|
|
else:
|
|
FNULL.close()
|
|
return True
|
|
except:
|
|
return False
|
|
|
|
@staticmethod
|
|
def updateRepoURL():
|
|
command = "sed -i 's|sgp.cyberpanel.sh|cdn.cyberpanel.sh|g' /etc/yum.repos.d/MariaDB.repo"
|
|
Upgrade.executioner(command, command, 0)
|
|
|
|
command = "sed -i 's|lax.cyberpanel.sh|cdn.cyberpanel.sh|g' /etc/yum.repos.d/MariaDB.repo"
|
|
Upgrade.executioner(command, command, 0)
|
|
|
|
command = "sed -i 's|fra.cyberpanel.sh|cdn.cyberpanel.sh|g' /etc/yum.repos.d/MariaDB.repo"
|
|
Upgrade.executioner(command, command, 0)
|
|
|
|
command = "sed -i 's|mirror.cyberpanel.net|cdn.cyberpanel.sh|g' /etc/yum.repos.d/MariaDB.repo"
|
|
Upgrade.executioner(command, command, 0)
|
|
|
|
command = "sed -i 's|sgp.cyberpanel.sh|cdn.cyberpanel.sh|g' /etc/yum.repos.d/litespeed.repo"
|
|
Upgrade.executioner(command, command, 0)
|
|
|
|
command = "sed -i 's|lax.cyberpanel.sh|cdn.cyberpanel.sh|g' /etc/yum.repos.d/litespeed.repo"
|
|
Upgrade.executioner(command, command, 0)
|
|
|
|
command = "sed -i 's|fra.cyberpanel.sh|cdn.cyberpanel.sh|g' /etc/yum.repos.d/litespeed.repo"
|
|
Upgrade.executioner(command, command, 0)
|
|
|
|
command = "sed -i 's|mirror.cyberpanel.net|cdn.cyberpanel.sh|g' /etc/yum.repos.d/litespeed.repo"
|
|
Upgrade.executioner(command, command, 0)
|
|
|
|
@staticmethod
|
|
def mountTemp():
|
|
try:
|
|
|
|
if os.path.exists("/usr/.tempdisk"):
|
|
return 0
|
|
|
|
command = "dd if=/dev/zero of=/usr/.tempdisk bs=100M count=15"
|
|
Upgrade.executioner(command, 'mountTemp', 0)
|
|
|
|
command = "mkfs.ext4 -F /usr/.tempdisk"
|
|
Upgrade.executioner(command, 'mountTemp', 0)
|
|
|
|
command = "mkdir -p /usr/.tmpbak/"
|
|
Upgrade.executioner(command, 'mountTemp', 0)
|
|
|
|
command = "cp -pr /tmp/* /usr/.tmpbak/"
|
|
subprocess.call(command, shell=True)
|
|
|
|
command = "mount -o loop,rw,nodev,nosuid,noexec,nofail /usr/.tempdisk /tmp"
|
|
Upgrade.executioner(command, 'mountTemp', 0)
|
|
|
|
command = "chmod 1777 /tmp"
|
|
Upgrade.executioner(command, 'mountTemp', 0)
|
|
|
|
command = "cp -pr /usr/.tmpbak/* /tmp/"
|
|
subprocess.call(command, shell=True)
|
|
|
|
command = "rm -rf /usr/.tmpbak"
|
|
Upgrade.executioner(command, 'mountTemp', 0)
|
|
|
|
command = "mount --bind /tmp /var/tmp"
|
|
Upgrade.executioner(command, 'mountTemp', 0)
|
|
|
|
tmp = "/usr/.tempdisk /tmp ext4 loop,rw,noexec,nosuid,nodev,nofail 0 0\n"
|
|
varTmp = "/tmp /var/tmp none bind 0 0\n"
|
|
|
|
fstab = "/etc/fstab"
|
|
writeToFile = open(fstab, "a")
|
|
writeToFile.writelines(tmp)
|
|
writeToFile.writelines(varTmp)
|
|
writeToFile.close()
|
|
|
|
except Exception as e:
|
|
ErrorSanitizer.log_error_securely(e, 'mountTemp')
|
|
Upgrade.stdOut("Failed to mount temporary filesystem [mountTemp]", 0)
|
|
|
|
@staticmethod
|
|
def dockerUsers():
|
|
### Docker User/group
|
|
try:
|
|
pwd.getpwnam('docker')
|
|
except KeyError:
|
|
command = "adduser docker"
|
|
Upgrade.executioner(command, 'adduser docker', 0)
|
|
|
|
try:
|
|
grp.getgrnam('docker')
|
|
except KeyError:
|
|
command = 'groupadd docker'
|
|
Upgrade.executioner(command, 'adduser docker', 0)
|
|
|
|
command = 'usermod -aG docker docker'
|
|
Upgrade.executioner(command, 'adduser docker', 0)
|
|
|
|
command = 'usermod -aG docker cyberpanel'
|
|
Upgrade.executioner(command, 'adduser docker', 0)
|
|
|
|
###
|
|
|
|
@staticmethod
|
|
def fixSudoers():
|
|
try:
|
|
distroPath = '/etc/lsb-release'
|
|
|
|
if os.path.exists(distroPath):
|
|
fileName = '/etc/sudoers'
|
|
data = open(fileName, 'r').readlines()
|
|
|
|
writeDataToFile = open(fileName, 'w')
|
|
for line in data:
|
|
if line.find("%sudo ALL=(ALL:ALL)") > -1:
|
|
continue
|
|
else:
|
|
writeDataToFile.write(line)
|
|
writeDataToFile.close()
|
|
|
|
else:
|
|
try:
|
|
path = "/etc/sudoers"
|
|
|
|
data = open(path, 'r').readlines()
|
|
|
|
writeToFile = open(path, 'w')
|
|
|
|
for items in data:
|
|
if items.find("wheel") > -1 and items.find("ALL=(ALL)"):
|
|
continue
|
|
elif items.find("root") > -1 and items.find("ALL=(ALL)") > -1 and items[0] != '#':
|
|
writeToFile.writelines('root ALL=(ALL:ALL) ALL\n')
|
|
else:
|
|
writeToFile.writelines(items)
|
|
|
|
writeToFile.close()
|
|
except:
|
|
pass
|
|
|
|
command = "chsh -s /bin/false cyberpanel"
|
|
Upgrade.executioner(command, 0)
|
|
except IOError as err:
|
|
pass
|
|
|
|
@staticmethod
|
|
def detectArchitecture():
|
|
"""Detect system architecture - custom binaries only for x86_64"""
|
|
try:
|
|
import platform
|
|
arch = platform.machine()
|
|
return arch == "x86_64"
|
|
except Exception as msg:
|
|
Upgrade.stdOut(str(msg) + " [detectArchitecture]", 0)
|
|
return False
|
|
|
|
@staticmethod
|
|
def detectPlatform():
|
|
"""Detect OS platform for binary selection (rhel8, rhel9, ubuntu)"""
|
|
try:
|
|
# Check for Ubuntu
|
|
if os.path.exists('/etc/lsb-release'):
|
|
with open('/etc/lsb-release', 'r') as f:
|
|
content = f.read()
|
|
if 'Ubuntu' in content or 'ubuntu' in content:
|
|
return 'ubuntu'
|
|
|
|
# Check for RHEL-based distributions
|
|
if os.path.exists('/etc/os-release'):
|
|
with open('/etc/os-release', 'r') as f:
|
|
content = f.read().lower()
|
|
|
|
# Check for version 8.x (RHEL, AlmaLinux, Rocky, CloudLinux, CentOS 8)
|
|
if 'version="8.' in content or 'version_id="8.' in content:
|
|
if any(distro in content for distro in ['red hat', 'almalinux', 'rocky', 'cloudlinux', 'centos']):
|
|
return 'rhel8'
|
|
|
|
# Check for version 9.x
|
|
if 'version="9.' in content or 'version_id="9.' in content:
|
|
if any(distro in content for distro in ['red hat', 'almalinux', 'rocky', 'cloudlinux', 'centos']):
|
|
return 'rhel9'
|
|
|
|
# Default to rhel8 if can't detect (safer default - rhel9 binaries may require GLIBC 2.35)
|
|
Upgrade.stdOut("WARNING: Could not detect platform, defaulting to rhel8", 0)
|
|
return 'rhel8'
|
|
|
|
except Exception as msg:
|
|
Upgrade.stdOut(f"ERROR detecting platform: {msg}, defaulting to rhel8", 0)
|
|
return 'rhel8'
|
|
|
|
@staticmethod
|
|
def getSystemGLIBCVersion():
|
|
"""Get the system's GLIBC version"""
|
|
try:
|
|
import subprocess
|
|
# Try to get GLIBC version from ldd
|
|
result = subprocess.run(['ldd', '--version'], capture_output=True, text=True, timeout=5)
|
|
if result.returncode == 0:
|
|
# ldd --version output format: "ldd (GNU libc) 2.34"
|
|
for line in result.stdout.split('\n'):
|
|
if 'GNU libc' in line or 'glibc' in line.lower():
|
|
import re
|
|
version_match = re.search(r'(\d+)\.(\d+)', line)
|
|
if version_match:
|
|
major = int(version_match.group(1))
|
|
minor = int(version_match.group(2))
|
|
return (major, minor)
|
|
|
|
# Fallback: try to read from libc.so.6
|
|
try:
|
|
result = subprocess.run(['/lib64/libc.so.6'], capture_output=True, text=True, timeout=5)
|
|
if result.returncode != 0 and 'version' in result.stderr.lower():
|
|
import re
|
|
version_match = re.search(r'(\d+)\.(\d+)', result.stderr)
|
|
if version_match:
|
|
major = int(version_match.group(1))
|
|
minor = int(version_match.group(2))
|
|
return (major, minor)
|
|
except:
|
|
pass
|
|
|
|
# If we can't detect, assume a safe minimum
|
|
Upgrade.stdOut("WARNING: Could not detect GLIBC version, assuming 2.34", 0)
|
|
return (2, 34)
|
|
except Exception as msg:
|
|
Upgrade.stdOut(f"WARNING: Error detecting GLIBC version: {msg}, assuming 2.34", 0)
|
|
return (2, 34)
|
|
|
|
@staticmethod
|
|
def checkBinaryGLIBCRequirements(binary_path):
|
|
"""Check GLIBC version requirements of a binary file"""
|
|
try:
|
|
import subprocess
|
|
import re
|
|
|
|
# Use objdump to check GLIBC version requirements
|
|
# objdump -T shows dynamic symbols and their GLIBC version requirements
|
|
result = subprocess.run(['objdump', '-T', binary_path], capture_output=True, text=True, timeout=10)
|
|
|
|
if result.returncode != 0:
|
|
# objdump might not be available, try readelf
|
|
result = subprocess.run(['readelf', '-d', binary_path], capture_output=True, text=True, timeout=10)
|
|
if result.returncode != 0:
|
|
Upgrade.stdOut("WARNING: Could not check binary GLIBC requirements (objdump/readelf not available)", 0)
|
|
return None
|
|
|
|
# Look for GLIBC version requirements in the output
|
|
# Format: GLIBC_2.35, GLIBC_2.34, etc.
|
|
max_version = None
|
|
for line in result.stdout.split('\n') + result.stderr.split('\n'):
|
|
# Look for GLIBC version symbols
|
|
matches = re.findall(r'GLIBC_(\d+)\.(\d+)', line)
|
|
for match in matches:
|
|
major = int(match[0])
|
|
minor = int(match[1])
|
|
if max_version is None or (major, minor) > max_version:
|
|
max_version = (major, minor)
|
|
|
|
return max_version
|
|
|
|
except FileNotFoundError:
|
|
# objdump/readelf not available
|
|
Upgrade.stdOut("WARNING: objdump/readelf not available, skipping GLIBC check", 0)
|
|
return None
|
|
except Exception as msg:
|
|
Upgrade.stdOut(f"WARNING: Error checking binary GLIBC requirements: {msg}", 0)
|
|
return None
|
|
|
|
@staticmethod
|
|
def verifyBinaryCompatibility(binary_path):
|
|
"""Verify that a binary is compatible with the system's GLIBC version"""
|
|
try:
|
|
system_glibc = Upgrade.getSystemGLIBCVersion()
|
|
binary_glibc = Upgrade.checkBinaryGLIBCRequirements(binary_path)
|
|
|
|
if binary_glibc is None:
|
|
# Can't check, but we can try a test run
|
|
Upgrade.stdOut("Cannot verify GLIBC requirements, performing test run...", 0)
|
|
return Upgrade.testBinaryExecution(binary_path)
|
|
|
|
Upgrade.stdOut(f"System GLIBC: {system_glibc[0]}.{system_glibc[1]}", 0)
|
|
Upgrade.stdOut(f"Binary requires GLIBC: {binary_glibc[0]}.{binary_glibc[1]}", 0)
|
|
|
|
# Check if binary requires newer GLIBC than system has
|
|
if binary_glibc > system_glibc:
|
|
Upgrade.stdOut(f"ERROR: Binary requires GLIBC {binary_glibc[0]}.{binary_glibc[1]}, but system has {system_glibc[0]}.{system_glibc[1]}", 0)
|
|
return False
|
|
|
|
Upgrade.stdOut("GLIBC compatibility check passed", 0)
|
|
return True
|
|
|
|
except Exception as msg:
|
|
Upgrade.stdOut(f"WARNING: Error verifying binary compatibility: {msg}", 0)
|
|
# If we can't verify, try test execution
|
|
return Upgrade.testBinaryExecution(binary_path)
|
|
|
|
@staticmethod
|
|
def testBinaryExecution(binary_path):
|
|
"""Test if binary can execute (checks GLIBC compatibility indirectly)"""
|
|
try:
|
|
import subprocess
|
|
# Try to run the binary with --version or -v flag
|
|
# This will fail immediately if GLIBC is incompatible
|
|
# The error format is: "./binary: /lib64/libc.so.6: version `GLIBC_X.Y' not found"
|
|
result = subprocess.run([binary_path, '--version'], capture_output=True, text=True, timeout=5)
|
|
|
|
# Check both stdout and stderr for GLIBC errors
|
|
output = result.stdout + result.stderr
|
|
|
|
# Look for GLIBC version not found errors
|
|
if 'GLIBC' in output and ('not found' in output or 'version' in output.lower()):
|
|
# Extract the required GLIBC version from error message
|
|
import re
|
|
glibc_match = re.search(r"GLIBC_(\d+)\.(\d+)'?\s+not found", output)
|
|
if glibc_match:
|
|
required_major = int(glibc_match.group(1))
|
|
required_minor = int(glibc_match.group(2))
|
|
Upgrade.stdOut(f"ERROR: Binary requires GLIBC {required_major}.{required_minor} which is not available", 0)
|
|
else:
|
|
Upgrade.stdOut(f"ERROR: Binary GLIBC compatibility test failed: {output[:200]}", 0)
|
|
return False
|
|
|
|
# If binary executed (even with non-zero return code for --version), it's compatible
|
|
if result.returncode == 0 or len(result.stdout) > 0:
|
|
return True
|
|
|
|
# If we get here, binary might not support --version, try -v
|
|
result = subprocess.run([binary_path, '-v'], capture_output=True, text=True, timeout=5)
|
|
output = result.stdout + result.stderr
|
|
|
|
if 'GLIBC' in output and ('not found' in output or 'version' in output.lower()):
|
|
import re
|
|
glibc_match = re.search(r"GLIBC_(\d+)\.(\d+)'?\s+not found", output)
|
|
if glibc_match:
|
|
required_major = int(glibc_match.group(1))
|
|
required_minor = int(glibc_match.group(2))
|
|
Upgrade.stdOut(f"ERROR: Binary requires GLIBC {required_major}.{required_minor} which is not available", 0)
|
|
else:
|
|
Upgrade.stdOut(f"ERROR: Binary GLIBC compatibility test failed: {output[:200]}", 0)
|
|
return False
|
|
|
|
# If no GLIBC error and we got some output, assume compatible
|
|
if len(output) > 0:
|
|
return True
|
|
|
|
# If binary doesn't support --version/-v, try to check if it's executable
|
|
# by checking file type
|
|
try:
|
|
result = subprocess.run(['file', binary_path], capture_output=True, text=True, timeout=5)
|
|
if 'ELF' in result.stdout and 'executable' in result.stdout:
|
|
Upgrade.stdOut("WARNING: Cannot test binary execution, but file appears valid", 0)
|
|
return True
|
|
except:
|
|
pass
|
|
|
|
# Conservative approach: if we can't verify, assume incompatible to be safe
|
|
Upgrade.stdOut("WARNING: Could not verify binary execution, skipping installation for safety", 0)
|
|
return False
|
|
|
|
except subprocess.TimeoutExpired:
|
|
Upgrade.stdOut("WARNING: Binary test timed out, assuming compatible", 0)
|
|
return True
|
|
except FileNotFoundError as e:
|
|
# Binary file not found or command not found
|
|
Upgrade.stdOut(f"ERROR: Binary test failed - file or command not found: {e}", 0)
|
|
return False
|
|
except Exception as msg:
|
|
# Check if it's a GLIBC error in the exception itself
|
|
error_str = str(msg)
|
|
if 'GLIBC' in error_str and 'not found' in error_str:
|
|
Upgrade.stdOut(f"ERROR: Binary GLIBC compatibility test failed: {error_str}", 0)
|
|
return False
|
|
|
|
Upgrade.stdOut(f"WARNING: Could not test binary execution: {msg}", 0)
|
|
# Conservative approach: if we can't test, assume incompatible to be safe
|
|
return False
|
|
|
|
@staticmethod
|
|
def downloadCustomBinary(url, destination, expected_sha256=None):
|
|
"""Download custom binary file with optional checksum verification"""
|
|
try:
|
|
Upgrade.stdOut(f"Downloading {os.path.basename(destination)}...", 0)
|
|
|
|
# Use wget for better progress display
|
|
command = f'wget -q --show-progress {url} -O {destination}'
|
|
res = subprocess.call(shlex.split(command))
|
|
|
|
# Check if file was downloaded successfully by verifying it exists and has reasonable size
|
|
if os.path.exists(destination):
|
|
file_size = os.path.getsize(destination)
|
|
# Verify file size is reasonable (at least 10KB to avoid error pages/empty files)
|
|
if file_size > 10240: # 10KB
|
|
if file_size > 1048576: # 1MB
|
|
Upgrade.stdOut(f"Downloaded successfully ({file_size / (1024*1024):.2f} MB)", 0)
|
|
else:
|
|
Upgrade.stdOut(f"Downloaded successfully ({file_size / 1024:.2f} KB)", 0)
|
|
|
|
# Verify checksum if provided
|
|
if expected_sha256:
|
|
Upgrade.stdOut("Verifying checksum...", 0)
|
|
import hashlib
|
|
sha256_hash = hashlib.sha256()
|
|
with open(destination, "rb") as f:
|
|
for byte_block in iter(lambda: f.read(4096), b""):
|
|
sha256_hash.update(byte_block)
|
|
actual_sha256 = sha256_hash.hexdigest()
|
|
|
|
if actual_sha256 == expected_sha256:
|
|
Upgrade.stdOut("Checksum verified successfully", 0)
|
|
return True
|
|
else:
|
|
Upgrade.stdOut(f"ERROR: Checksum mismatch!", 0)
|
|
Upgrade.stdOut(f"Expected: {expected_sha256}", 0)
|
|
Upgrade.stdOut(f"Got: {actual_sha256}", 0)
|
|
return False
|
|
else:
|
|
return True
|
|
else:
|
|
Upgrade.stdOut(f"ERROR: Downloaded file too small ({file_size} bytes)", 0)
|
|
return False
|
|
else:
|
|
Upgrade.stdOut("ERROR: Download failed - file not found", 0)
|
|
return False
|
|
|
|
except Exception as msg:
|
|
Upgrade.stdOut(f"ERROR: {msg} [downloadCustomBinary]", 0)
|
|
return False
|
|
|
|
@staticmethod
|
|
def installCustomOLSBinaries():
|
|
"""Install custom OpenLiteSpeed binaries with PHP config support"""
|
|
try:
|
|
Upgrade.stdOut("Installing Custom OpenLiteSpeed Binaries", 0)
|
|
Upgrade.stdOut("=" * 50, 0)
|
|
|
|
# Check architecture
|
|
if not Upgrade.detectArchitecture():
|
|
Upgrade.stdOut("WARNING: Custom binaries only available for x86_64", 0)
|
|
Upgrade.stdOut("Skipping custom binary installation", 0)
|
|
Upgrade.stdOut("Standard OLS will be used", 0)
|
|
return True # Not a failure, just skip
|
|
|
|
# Detect platform
|
|
platform = Upgrade.detectPlatform()
|
|
Upgrade.stdOut(f"Detected platform: {platform}", 0)
|
|
|
|
# Platform-specific URLs and checksums (OpenLiteSpeed v1.8.4.1 with PHPConfig + Header unset fix + Static Linking)
|
|
# Module Build Date: December 28, 2025 - v2.2.0 Brute Force with Progressive Throttle
|
|
BINARY_CONFIGS = {
|
|
'rhel8': {
|
|
'url': 'https://cyberpanel.net/openlitespeed-phpconfig-x86_64-rhel8-static',
|
|
'sha256': '6ce688a237615102cc1603ee1999b3cede0ff3482d31e1f65705e92396d34b3a',
|
|
'module_url': 'https://cyberpanel.net/binaries/rhel8/cyberpanel_ols.so',
|
|
'module_sha256': '7c33d89c7fbcd3ed7b0422fee3f49b5e041713c2c2b7316a5774f6defa147572',
|
|
'modsec_url': 'https://cyberpanel.net/mod_security-compatible-rhel8.so',
|
|
'modsec_sha256': 'bbbf003bdc7979b98f09b640dffe2cbbe5f855427f41319e4c121403c05837b2'
|
|
},
|
|
'rhel9': {
|
|
'url': 'https://cyberpanel.net/openlitespeed-phpconfig-x86_64-rhel9-static',
|
|
'sha256': '709093d99d5d3e789134c131893614968e17eefd9ade2200f811d9b076b2f02e',
|
|
'module_url': 'https://cyberpanel.net/binaries/rhel9/cyberpanel_ols.so',
|
|
'module_sha256': 'ae65337e2d13babc0c675bb4264d469daffa2efb7627c9bf39ac59e42e3ebede',
|
|
'modsec_url': 'https://cyberpanel.net/mod_security-compatible-rhel.so',
|
|
'modsec_sha256': '19deb2ffbaf1334cf4ce4d46d53f747a75b29e835bf5a01f91ebcc0c78e98629'
|
|
},
|
|
'ubuntu': {
|
|
'url': 'https://cyberpanel.net/openlitespeed-phpconfig-x86_64-ubuntu-static',
|
|
'sha256': '89aaf66474e78cb3c1666784e0e7a417550bd317e6ab148201bdc318d36710cb',
|
|
'module_url': 'https://cyberpanel.net/binaries/ubuntu/cyberpanel_ols.so',
|
|
'module_sha256': '62978ede1f174dd2885e5227a3d9cc463d0c27acd77cfc23743d7309ee0c54ea',
|
|
'modsec_url': 'https://cyberpanel.net/mod_security-compatible-ubuntu.so',
|
|
'modsec_sha256': 'ed02c813136720bd4b9de5925f6e41bdc8392e494d7740d035479aaca6d1e0cd'
|
|
}
|
|
}
|
|
|
|
config = BINARY_CONFIGS.get(platform)
|
|
if not config:
|
|
Upgrade.stdOut(f"ERROR: No binaries available for platform {platform}", 0)
|
|
Upgrade.stdOut("Skipping custom binary installation", 0)
|
|
return True # Not fatal
|
|
|
|
OLS_BINARY_URL = config['url']
|
|
OLS_BINARY_SHA256 = config['sha256']
|
|
MODULE_URL = config['module_url']
|
|
MODULE_SHA256 = config['module_sha256']
|
|
MODSEC_URL = config.get('modsec_url')
|
|
MODSEC_SHA256 = config.get('modsec_sha256')
|
|
OLS_BINARY_PATH = "/usr/local/lsws/bin/openlitespeed"
|
|
MODULE_PATH = "/usr/local/lsws/modules/cyberpanel_ols.so"
|
|
MODSEC_PATH = "/usr/local/lsws/modules/mod_security.so"
|
|
|
|
# Create backup
|
|
from datetime import datetime
|
|
timestamp = datetime.now().strftime("%Y%m%d-%H%M%S")
|
|
backup_dir = f"/usr/local/lsws/backup-{timestamp}"
|
|
|
|
try:
|
|
os.makedirs(backup_dir, exist_ok=True)
|
|
if os.path.exists(OLS_BINARY_PATH):
|
|
shutil.copy2(OLS_BINARY_PATH, f"{backup_dir}/openlitespeed.backup")
|
|
Upgrade.stdOut(f"Backup created at: {backup_dir}", 0)
|
|
# Also backup existing ModSecurity if it exists
|
|
if os.path.exists(MODSEC_PATH):
|
|
shutil.copy2(MODSEC_PATH, f"{backup_dir}/mod_security.so.backup")
|
|
except Exception as e:
|
|
Upgrade.stdOut(f"WARNING: Could not create backup: {e}", 0)
|
|
|
|
# Download binaries to temp location
|
|
tmp_binary = "/tmp/openlitespeed-custom"
|
|
tmp_module = "/tmp/cyberpanel_ols.so"
|
|
tmp_modsec = "/tmp/mod_security.so"
|
|
|
|
Upgrade.stdOut("Downloading custom binaries...", 0)
|
|
|
|
# Download OpenLiteSpeed binary with checksum verification
|
|
if not Upgrade.downloadCustomBinary(OLS_BINARY_URL, tmp_binary, OLS_BINARY_SHA256):
|
|
Upgrade.stdOut("ERROR: Failed to download or verify OLS binary", 0)
|
|
Upgrade.stdOut("Continuing with standard OLS", 0)
|
|
return True # Not fatal, continue with standard OLS
|
|
|
|
# CRITICAL: Verify GLIBC compatibility before installation
|
|
Upgrade.stdOut("Verifying GLIBC compatibility...", 0)
|
|
if not Upgrade.verifyBinaryCompatibility(tmp_binary):
|
|
Upgrade.stdOut("=" * 50, 0)
|
|
Upgrade.stdOut("ERROR: Binary GLIBC requirements incompatible with system", 0)
|
|
Upgrade.stdOut("This binary would cause OpenLiteSpeed to fail to start", 0)
|
|
Upgrade.stdOut("Skipping custom binary installation to preserve system stability", 0)
|
|
Upgrade.stdOut("Standard OLS binary from package manager will be used", 0)
|
|
Upgrade.stdOut("=" * 50, 0)
|
|
# Clean up downloaded binary
|
|
try:
|
|
if os.path.exists(tmp_binary):
|
|
os.remove(tmp_binary)
|
|
except:
|
|
pass
|
|
return True # Not fatal, continue with standard OLS
|
|
|
|
# Download module with checksum verification (if available)
|
|
module_downloaded = False
|
|
if MODULE_URL and MODULE_SHA256:
|
|
if not Upgrade.downloadCustomBinary(MODULE_URL, tmp_module, MODULE_SHA256):
|
|
Upgrade.stdOut("ERROR: Failed to download or verify module", 0)
|
|
Upgrade.stdOut("Continuing with standard OLS", 0)
|
|
return True # Not fatal, continue with standard OLS
|
|
module_downloaded = True
|
|
else:
|
|
Upgrade.stdOut("Note: No CyberPanel module for this platform", 0)
|
|
|
|
# Download compatible ModSecurity if existing ModSecurity is installed
|
|
# This prevents ABI incompatibility crashes (Signal 11/SIGSEGV)
|
|
modsec_downloaded = False
|
|
if os.path.exists(MODSEC_PATH) and MODSEC_URL and MODSEC_SHA256:
|
|
Upgrade.stdOut("Existing ModSecurity detected - downloading compatible version...", 0)
|
|
if Upgrade.downloadCustomBinary(MODSEC_URL, tmp_modsec, MODSEC_SHA256):
|
|
modsec_downloaded = True
|
|
else:
|
|
Upgrade.stdOut("WARNING: Failed to download compatible ModSecurity", 0)
|
|
Upgrade.stdOut("ModSecurity may crash due to ABI incompatibility", 0)
|
|
Upgrade.stdOut("Consider manually updating ModSecurity after upgrade", 0)
|
|
|
|
# Install OpenLiteSpeed binary
|
|
Upgrade.stdOut("Installing custom binaries...", 0)
|
|
|
|
try:
|
|
# Make binary executable before moving
|
|
os.chmod(tmp_binary, 0o755)
|
|
|
|
# Final compatibility test before installation
|
|
if not Upgrade.testBinaryExecution(tmp_binary):
|
|
Upgrade.stdOut("ERROR: Final binary compatibility test failed", 0)
|
|
Upgrade.stdOut("Skipping installation to prevent OpenLiteSpeed failure", 0)
|
|
try:
|
|
if os.path.exists(tmp_binary):
|
|
os.remove(tmp_binary)
|
|
except:
|
|
pass
|
|
return True # Not fatal, continue with standard OLS
|
|
|
|
shutil.move(tmp_binary, OLS_BINARY_PATH)
|
|
Upgrade.stdOut("Installed OpenLiteSpeed binary", 0)
|
|
except Exception as e:
|
|
Upgrade.stdOut(f"ERROR: Failed to install binary: {e}", 0)
|
|
# Try to restore backup if installation failed
|
|
try:
|
|
if os.path.exists(f"{backup_dir}/openlitespeed.backup"):
|
|
shutil.copy2(f"{backup_dir}/openlitespeed.backup", OLS_BINARY_PATH)
|
|
Upgrade.stdOut("Restored original binary from backup", 0)
|
|
except:
|
|
pass
|
|
return False
|
|
|
|
# Install module (if downloaded)
|
|
if module_downloaded:
|
|
try:
|
|
os.makedirs(os.path.dirname(MODULE_PATH), exist_ok=True)
|
|
shutil.move(tmp_module, MODULE_PATH)
|
|
os.chmod(MODULE_PATH, 0o644)
|
|
Upgrade.stdOut("Installed CyberPanel module", 0)
|
|
except Exception as e:
|
|
Upgrade.stdOut(f"ERROR: Failed to install module: {e}", 0)
|
|
return False
|
|
|
|
# Install compatible ModSecurity (if downloaded)
|
|
if modsec_downloaded:
|
|
try:
|
|
shutil.move(tmp_modsec, MODSEC_PATH)
|
|
os.chmod(MODSEC_PATH, 0o644)
|
|
Upgrade.stdOut("Installed compatible ModSecurity module", 0)
|
|
except Exception as e:
|
|
Upgrade.stdOut(f"WARNING: Failed to install ModSecurity: {e}", 0)
|
|
# Non-fatal, continue
|
|
|
|
# Verify installation
|
|
if os.path.exists(OLS_BINARY_PATH):
|
|
if not module_downloaded or os.path.exists(MODULE_PATH):
|
|
Upgrade.stdOut("=" * 50, 0)
|
|
Upgrade.stdOut("Custom Binaries Installed Successfully", 0)
|
|
Upgrade.stdOut("Features enabled:", 0)
|
|
Upgrade.stdOut(" - Static-linked cross-platform binary", 0)
|
|
if module_downloaded:
|
|
Upgrade.stdOut(" - Apache-style .htaccess support", 0)
|
|
Upgrade.stdOut(" - php_value/php_flag directives", 0)
|
|
Upgrade.stdOut(" - Enhanced header control", 0)
|
|
Upgrade.stdOut(f"Backup: {backup_dir}", 0)
|
|
Upgrade.stdOut("=" * 50, 0)
|
|
# Configure module after installation
|
|
Upgrade.configureCustomModule()
|
|
return True
|
|
|
|
Upgrade.stdOut("ERROR: Installation verification failed", 0)
|
|
return False
|
|
|
|
except Exception as msg:
|
|
Upgrade.stdOut(f"ERROR: {msg} [installCustomOLSBinaries]", 0)
|
|
Upgrade.stdOut("Continuing with standard OLS", 0)
|
|
return True # Non-fatal error, continue
|
|
|
|
@staticmethod
|
|
def configureCustomModule():
|
|
"""Configure CyberPanel module in OpenLiteSpeed config"""
|
|
try:
|
|
Upgrade.stdOut("Configuring CyberPanel module...", 0)
|
|
|
|
CONFIG_FILE = "/usr/local/lsws/conf/httpd_config.conf"
|
|
|
|
if not os.path.exists(CONFIG_FILE):
|
|
Upgrade.stdOut("WARNING: Config file not found", 0)
|
|
Upgrade.stdOut("Module will be auto-loaded", 0)
|
|
return True
|
|
|
|
# Check if module is already configured
|
|
with open(CONFIG_FILE, 'r') as f:
|
|
content = f.read()
|
|
if 'cyberpanel_ols' in content:
|
|
Upgrade.stdOut("Module already configured", 0)
|
|
return True
|
|
|
|
# Add module configuration
|
|
module_config = """
|
|
module cyberpanel_ols {
|
|
ls_enabled 1
|
|
}
|
|
"""
|
|
# Backup config
|
|
shutil.copy2(CONFIG_FILE, f"{CONFIG_FILE}.backup")
|
|
|
|
# Append module config
|
|
with open(CONFIG_FILE, 'a') as f:
|
|
f.write(module_config)
|
|
|
|
Upgrade.stdOut("Module configured successfully", 0)
|
|
return True
|
|
|
|
except Exception as msg:
|
|
Upgrade.stdOut(f"WARNING: Module configuration failed: {msg}", 0)
|
|
Upgrade.stdOut("Module may still work via auto-load", 0)
|
|
return True # Non-fatal
|
|
|
|
@staticmethod
|
|
def download_install_phpmyadmin():
|
|
try:
|
|
cwd = os.getcwd()
|
|
|
|
if not os.path.exists("/usr/local/CyberCP/public"):
|
|
os.mkdir("/usr/local/CyberCP/public")
|
|
|
|
try:
|
|
shutil.rmtree("/usr/local/CyberCP/public/phpmyadmin")
|
|
except:
|
|
pass
|
|
|
|
# Try to fetch latest phpMyAdmin version from GitHub
|
|
phpmyadmin_version = '5.2.2' # Fallback version
|
|
try:
|
|
from plogical.versionFetcher import get_latest_phpmyadmin_version
|
|
latest_version = get_latest_phpmyadmin_version()
|
|
if latest_version and latest_version != phpmyadmin_version:
|
|
Upgrade.stdOut(f"Using latest phpMyAdmin version: {latest_version}", 0)
|
|
phpmyadmin_version = latest_version
|
|
else:
|
|
Upgrade.stdOut(f"Using fallback phpMyAdmin version: {phpmyadmin_version}", 0)
|
|
except Exception as e:
|
|
Upgrade.stdOut(f"Failed to fetch latest phpMyAdmin version, using fallback: {e}", 0)
|
|
|
|
Upgrade.stdOut("Installing phpMyAdmin...", 0)
|
|
|
|
command = f'wget -q -O /usr/local/CyberCP/public/phpmyadmin.tar.gz https://files.phpmyadmin.net/phpMyAdmin/{phpmyadmin_version}/phpMyAdmin-{phpmyadmin_version}-all-languages.tar.gz'
|
|
Upgrade.executioner_silent(command, f'Download phpMyAdmin {phpmyadmin_version}')
|
|
|
|
command = 'tar -xzf /usr/local/CyberCP/public/phpmyadmin.tar.gz -C /usr/local/CyberCP/public/'
|
|
Upgrade.executioner_silent(command, 'Extract phpMyAdmin')
|
|
|
|
command = 'mv /usr/local/CyberCP/public/phpMyAdmin-*-all-languages /usr/local/CyberCP/public/phpmyadmin'
|
|
subprocess.call(command, shell=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
|
|
|
command = 'rm -f /usr/local/CyberCP/public/phpmyadmin.tar.gz'
|
|
Upgrade.executioner_silent(command, 'Cleanup phpMyAdmin tar.gz')
|
|
|
|
Upgrade.stdOut("phpMyAdmin installation completed.", 0)
|
|
|
|
## Write secret phrase
|
|
|
|
rString = ''.join([random.choice(string.ascii_letters + string.digits) for n in range(32)])
|
|
|
|
data = open('/usr/local/CyberCP/public/phpmyadmin/config.sample.inc.php', 'r').readlines()
|
|
|
|
writeToFile = open('/usr/local/CyberCP/public/phpmyadmin/config.inc.php', 'w')
|
|
|
|
writeE = 1
|
|
|
|
phpMyAdminContent = """
|
|
$cfg['Servers'][$i]['AllowNoPassword'] = false;
|
|
$cfg['Servers'][$i]['auth_type'] = 'signon';
|
|
$cfg['Servers'][$i]['SignonSession'] = 'SignonSession';
|
|
$cfg['Servers'][$i]['SignonURL'] = 'phpmyadminsignin.php';
|
|
$cfg['Servers'][$i]['LogoutURL'] = 'phpmyadminsignin.php?logout';
|
|
"""
|
|
|
|
for items in data:
|
|
if items.find('blowfish_secret') > -1:
|
|
writeToFile.writelines(
|
|
"$cfg['blowfish_secret'] = '" + rString + "'; /* YOU MUST FILL IN THIS FOR COOKIE AUTH! */\n")
|
|
elif items.find('/* Authentication type */') > -1:
|
|
writeToFile.writelines(items)
|
|
writeToFile.write(phpMyAdminContent)
|
|
writeE = 0
|
|
elif items.find("$cfg['Servers'][$i]['AllowNoPassword']") > -1:
|
|
writeE = 1
|
|
else:
|
|
if writeE:
|
|
writeToFile.writelines(items)
|
|
|
|
writeToFile.writelines("$cfg['TempDir'] = '/usr/local/CyberCP/public/phpmyadmin/tmp';\n")
|
|
|
|
writeToFile.close()
|
|
|
|
os.mkdir('/usr/local/CyberCP/public/phpmyadmin/tmp')
|
|
|
|
command = 'cp /usr/local/CyberCP/plogical/phpmyadminsignin.php /usr/local/CyberCP/public/phpmyadmin/phpmyadminsignin.php'
|
|
Upgrade.executioner(command, 0)
|
|
|
|
passFile = "/etc/cyberpanel/mysqlPassword"
|
|
|
|
try:
|
|
import json
|
|
jsonData = json.loads(open(passFile, 'r').read())
|
|
|
|
mysqluser = jsonData['mysqluser']
|
|
mysqlpassword = jsonData['mysqlpassword']
|
|
mysqlport = jsonData['mysqlport']
|
|
mysqlhost = jsonData['mysqlhost']
|
|
|
|
command = "sed -i 's|localhost|%s|g' /usr/local/CyberCP/public/phpmyadmin/phpmyadminsignin.php" % (
|
|
mysqlhost)
|
|
Upgrade.executioner(command, 0)
|
|
|
|
except:
|
|
pass
|
|
|
|
os.chdir(cwd)
|
|
|
|
except Exception as e:
|
|
ErrorSanitizer.log_error_securely(e, 'download_install_phpmyadmin')
|
|
Upgrade.stdOut("Failed to download and install phpMyAdmin [download_install_phpmyadmin]", 0)
|
|
|
|
@staticmethod
|
|
def setupComposer():
|
|
|
|
if os.path.exists('composer.sh'):
|
|
os.remove('composer.sh')
|
|
|
|
command = "wget https://cyberpanel.sh/composer.sh"
|
|
Upgrade.executioner(command, 0)
|
|
|
|
command = "chmod +x composer.sh"
|
|
Upgrade.executioner(command, 0)
|
|
|
|
command = "./composer.sh"
|
|
Upgrade.executioner(command, 0)
|
|
|
|
@staticmethod
|
|
def downoad_and_install_raindloop():
|
|
try:
|
|
#######
|
|
|
|
# if os.path.exists("/usr/local/CyberCP/public/rainloop"):
|
|
#
|
|
# if os.path.exists("/usr/local/lscp/cyberpanel/rainloop/data"):
|
|
# pass
|
|
# else:
|
|
# command = "mv /usr/local/CyberCP/public/rainloop/data /usr/local/lscp/cyberpanel/rainloop/data"
|
|
# Upgrade.executioner(command, 0)
|
|
#
|
|
# command = "chown -R lscpd:lscpd /usr/local/lscp/cyberpanel/rainloop/data"
|
|
# Upgrade.executioner(command, 0)
|
|
#
|
|
# iPath = os.listdir('/usr/local/CyberCP/public/rainloop/rainloop/v/')
|
|
#
|
|
# path = "/usr/local/CyberCP/public/snappymail/snappymail/v/%s/include.php" % (iPath[0])
|
|
#
|
|
# data = open(path, 'r').readlines()
|
|
# writeToFile = open(path, 'w')
|
|
#
|
|
# for items in data:
|
|
# if items.find("$sCustomDataPath = '';") > -1:
|
|
# writeToFile.writelines(
|
|
# " $sCustomDataPath = '/usr/local/lscp/cyberpanel/rainloop/data';\n")
|
|
# else:
|
|
# writeToFile.writelines(items)
|
|
#
|
|
# writeToFile.close()
|
|
# return 0
|
|
|
|
cwd = os.getcwd()
|
|
|
|
if not os.path.exists("/usr/local/CyberCP/public"):
|
|
os.mkdir("/usr/local/CyberCP/public")
|
|
|
|
# Try to fetch latest SnappyMail version from GitHub
|
|
try:
|
|
from plogical.versionFetcher import get_latest_snappymail_version
|
|
latest_version = get_latest_snappymail_version()
|
|
if latest_version and latest_version != Upgrade.SnappyVersion:
|
|
Upgrade.stdOut(f"Using latest SnappyMail version: {latest_version}", 0)
|
|
Upgrade.SnappyVersion = latest_version
|
|
else:
|
|
Upgrade.stdOut(f"Using fallback SnappyMail version: {Upgrade.SnappyVersion}", 0)
|
|
except Exception as e:
|
|
Upgrade.stdOut(f"Failed to fetch latest SnappyMail version, using fallback: {e}", 0)
|
|
|
|
os.chdir("/usr/local/CyberCP/public")
|
|
|
|
count = 1
|
|
|
|
Upgrade.stdOut("Installing SnappyMail...", 0)
|
|
|
|
while (1):
|
|
command = 'wget -q https://github.com/the-djmaze/snappymail/releases/download/v%s/snappymail-%s.zip' % (
|
|
Upgrade.SnappyVersion, Upgrade.SnappyVersion)
|
|
cmd = shlex.split(command)
|
|
res = subprocess.call(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
|
if res != 0:
|
|
count = count + 1
|
|
if count == 3:
|
|
break
|
|
else:
|
|
break
|
|
|
|
#############
|
|
|
|
count = 0
|
|
|
|
if os.path.exists('/usr/local/CyberCP/public/snappymail'):
|
|
shutil.rmtree('/usr/local/CyberCP/public/snappymail')
|
|
|
|
while (1):
|
|
command = 'unzip -q snappymail-%s.zip -d /usr/local/CyberCP/public/snappymail' % (Upgrade.SnappyVersion)
|
|
|
|
cmd = shlex.split(command)
|
|
res = subprocess.call(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
|
if res != 0:
|
|
count = count + 1
|
|
if count == 3:
|
|
break
|
|
else:
|
|
break
|
|
try:
|
|
os.remove("snappymail-%s.zip" % (Upgrade.SnappyVersion))
|
|
except:
|
|
pass
|
|
|
|
#######
|
|
|
|
os.chdir("/usr/local/CyberCP/public/snappymail")
|
|
|
|
count = 0
|
|
|
|
while (1):
|
|
command = 'find . -type d -exec chmod 755 {} \;'
|
|
cmd = shlex.split(command)
|
|
res = subprocess.call(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
|
if res != 0:
|
|
count = count + 1
|
|
if count == 3:
|
|
break
|
|
else:
|
|
break
|
|
|
|
#############
|
|
|
|
count = 0
|
|
|
|
while (1):
|
|
command = 'find . -type f -exec chmod 644 {} \;'
|
|
cmd = shlex.split(command)
|
|
res = subprocess.call(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
|
if res != 0:
|
|
count = count + 1
|
|
if count == 3:
|
|
break
|
|
else:
|
|
break
|
|
######
|
|
|
|
iPath = os.listdir('/usr/local/CyberCP/public/snappymail/snappymail/v/')
|
|
|
|
path = "/usr/local/CyberCP/public/snappymail/snappymail/v/%s/include.php" % (iPath[0])
|
|
|
|
data = open(path, 'r').readlines()
|
|
writeToFile = open(path, 'w')
|
|
|
|
for items in data:
|
|
if items.find("$sCustomDataPath = '';") > -1:
|
|
writeToFile.writelines(
|
|
" $sCustomDataPath = '/usr/local/lscp/cyberpanel/rainloop/data';\n")
|
|
else:
|
|
writeToFile.writelines(items)
|
|
|
|
writeToFile.close()
|
|
|
|
command = "mkdir -p /usr/local/lscp/cyberpanel/rainloop/data/_data_/_default_/configs/"
|
|
Upgrade.executioner_silent(command, 'mkdir snappymail configs', 0)
|
|
|
|
command = f'wget -q -O /usr/local/CyberCP/snappymail_cyberpanel.php https://raw.githubusercontent.com/the-djmaze/snappymail/master/integrations/cyberpanel/install.php'
|
|
Upgrade.executioner_silent(command, 'verify certificate', 0)
|
|
|
|
command = f'/usr/local/lsws/lsphp83/bin/php /usr/local/CyberCP/snappymail_cyberpanel.php'
|
|
Upgrade.executioner_silent(command, 'verify certificate', 0)
|
|
|
|
# labsPath = '/usr/local/lscp/cyberpanel/rainloop/data/_data_/_default_/configs/application.ini'
|
|
|
|
# labsData = """[labs]
|
|
# imap_folder_list_limit = 0
|
|
# autocreate_system_folders = On
|
|
# """
|
|
#
|
|
# writeToFile = open(labsPath, 'a')
|
|
# writeToFile.write(labsData)
|
|
# writeToFile.close()
|
|
|
|
includeFileOldPath = '/usr/local/CyberCP/public/snappymail/_include.php'
|
|
includeFileNewPath = '/usr/local/CyberCP/public/snappymail/include.php'
|
|
|
|
# if os.path.exists(includeFileOldPath):
|
|
# writeToFile = open(includeFileOldPath, 'a')
|
|
# writeToFile.write("\ndefine('APP_DATA_FOLDER_PATH', '/usr/local/lscp/cyberpanel/rainloop/data/');\n")
|
|
# writeToFile.close()
|
|
|
|
# command = 'mv %s %s' % (includeFileOldPath, includeFileNewPath)
|
|
# Upgrade.executioner(command, 'mkdir snappymail configs', 0)
|
|
|
|
## take care of auto create folders
|
|
|
|
## Disable local cert verification
|
|
|
|
# command = "sed -i 's|verify_certificate = On|verify_certificate = Off|g' %s" % (labsPath)
|
|
# Upgrade.executioner(command, 'verify certificate', 0)
|
|
|
|
# labsData = open(labsPath, 'r').read()
|
|
# labsDataLines = open(labsPath, 'r').readlines()
|
|
#
|
|
# if labsData.find('autocreate_system_folders') > -1:
|
|
# command = "sed -i 's|autocreate_system_folders = Off|autocreate_system_folders = On|g' %s" % (labsPath)
|
|
# Upgrade.executioner(command, 'mkdir snappymail configs', 0)
|
|
# else:
|
|
# WriteToFile = open(labsPath, 'w')
|
|
# for lines in labsDataLines:
|
|
# if lines.find('[labs]') > -1:
|
|
# WriteToFile.write(lines)
|
|
# WriteToFile.write(f'autocreate_system_folders = On\n')
|
|
# else:
|
|
# WriteToFile.write(lines)
|
|
# WriteToFile.close()
|
|
|
|
##take care of imap_folder_list_limit
|
|
|
|
# labsDataLines = open(labsPath, 'r').readlines()
|
|
#
|
|
# if labsData.find('imap_folder_list_limit') == -1:
|
|
# WriteToFile = open(labsPath, 'w')
|
|
# for lines in labsDataLines:
|
|
# if lines.find('[labs]') > -1:
|
|
# WriteToFile.write(lines)
|
|
# WriteToFile.write(f'imap_folder_list_limit = 0\n')
|
|
# else:
|
|
# WriteToFile.write(lines)
|
|
# WriteToFile.close()
|
|
|
|
### now download and install actual plugin
|
|
|
|
# command = f'mkdir /usr/local/lscp/cyberpanel/rainloop/data/_data_/_default_/plugins/mailbox-detect'
|
|
# Upgrade.executioner(command, 'verify certificate', 0)
|
|
#
|
|
# command = f'chmod 700 /usr/local/lscp/cyberpanel/rainloop/data/_data_/_default_/plugins/mailbox-detect'
|
|
# Upgrade.executioner(command, 'verify certificate', 0)
|
|
#
|
|
# command = f'chown lscpd:lscpd /usr/local/lscp/cyberpanel/rainloop/data/_data_/_default_/plugins/mailbox-detect'
|
|
# Upgrade.executioner(command, 'verify certificate', 0)
|
|
#
|
|
# command = f'wget -O /usr/local/lscp/cyberpanel/rainloop/data/_data_/_default_/plugins/mailbox-detect/index.php https://raw.githubusercontent.com/the-djmaze/snappymail/master/plugins/mailbox-detect/index.php'
|
|
# Upgrade.executioner(command, 'verify certificate', 0)
|
|
#
|
|
# command = f'chmod 644 /usr/local/lscp/cyberpanel/rainloop/data/_data_/_default_/plugins/mailbox-detect/index.php'
|
|
# Upgrade.executioner(command, 'verify certificate', 0)
|
|
#
|
|
# command = f'chown lscpd:lscpd /usr/local/lscp/cyberpanel/rainloop/data/_data_/_default_/plugins/mailbox-detect/index.php'
|
|
# Upgrade.executioner(command, 'verify certificate', 0)
|
|
#
|
|
# ### Enable plugins and enable mailbox creation plugin
|
|
#
|
|
# labsDataLines = open(labsPath, 'r').readlines()
|
|
# PluginsActivator = 0
|
|
# WriteToFile = open(labsPath, 'w')
|
|
#
|
|
#
|
|
# for lines in labsDataLines:
|
|
# if lines.find('[plugins]') > -1:
|
|
# PluginsActivator = 1
|
|
# WriteToFile.write(lines)
|
|
# elif PluginsActivator and lines.find('enable = ') > -1:
|
|
# WriteToFile.write(f'enable = On\n')
|
|
# elif PluginsActivator and lines.find('enabled_list = ') > -1:
|
|
# WriteToFile.write(f'enabled_list = "mailbox-detect"\n')
|
|
# elif PluginsActivator == 1 and lines.find('[defaults]') > -1:
|
|
# PluginsActivator = 0
|
|
# WriteToFile.write(lines)
|
|
# else:
|
|
# WriteToFile.write(lines)
|
|
# WriteToFile.close()
|
|
#
|
|
# ## enable auto create in the enabled plugin
|
|
# PluginsFilePath = '/usr/local/lscp/cyberpanel/rainloop/data/_data_/_default_/configs/plugin-mailbox-detect.json'
|
|
#
|
|
# WriteToFile = open(PluginsFilePath, 'w')
|
|
# WriteToFile.write("""{
|
|
# "plugin": {
|
|
# "autocreate_system_folders": true
|
|
# }
|
|
# }
|
|
# """)
|
|
# WriteToFile.close()
|
|
#
|
|
# command = f'chown lscpd:lscpd {PluginsFilePath}'
|
|
# Upgrade.executioner(command, 'verify certificate', 0)
|
|
#
|
|
# command = f'chmod 600 {PluginsFilePath}'
|
|
# Upgrade.executioner(command, 'verify certificate', 0)
|
|
|
|
os.chdir(cwd)
|
|
|
|
Upgrade.stdOut("SnappyMail installation completed.", 0)
|
|
|
|
except Exception as e:
|
|
ErrorSanitizer.log_error_securely(e, 'downoad_and_install_raindloop')
|
|
Upgrade.stdOut("Failed to download and install Rainloop [downoad_and_install_raindloop]", 0)
|
|
|
|
return 1
|
|
|
|
@staticmethod
|
|
def downloadLink():
|
|
try:
|
|
version_number = VERSION
|
|
version_build = str(BUILD)
|
|
|
|
try:
|
|
Content = {"version":version_number,"build":version_build}
|
|
path = "/usr/local/CyberCP/version.txt"
|
|
writeToFile = open(path, 'w')
|
|
writeToFile.write(json.dumps(Content))
|
|
writeToFile.close()
|
|
except:
|
|
pass
|
|
|
|
return (version_number + "." + version_build + ".tar.gz")
|
|
except Exception as e:
|
|
ErrorSanitizer.log_error_securely(e, 'downloadLink')
|
|
Upgrade.stdOut("Failed to download required files [downloadLink]")
|
|
os._exit(0)
|
|
|
|
@staticmethod
|
|
def setupCLI():
|
|
try:
|
|
|
|
command = "ln -s /usr/local/CyberCP/cli/cyberPanel.py /usr/bin/cyberpanel"
|
|
Upgrade.executioner(command, 'CLI Symlink', 0)
|
|
|
|
command = "chmod +x /usr/local/CyberCP/cli/cyberPanel.py"
|
|
Upgrade.executioner(command, 'CLI Permissions', 0)
|
|
|
|
except OSError as e:
|
|
ErrorSanitizer.log_error_securely(e, 'setupCLI')
|
|
Upgrade.stdOut("Failed to setup CLI [setupCLI]")
|
|
return 0
|
|
|
|
@staticmethod
|
|
def staticContent():
|
|
|
|
command = "rm -rf /usr/local/CyberCP/public/static"
|
|
Upgrade.executioner(command, 'Remove old static content', 0)
|
|
|
|
##
|
|
|
|
if not os.path.exists("/usr/local/CyberCP/public"):
|
|
os.mkdir("/usr/local/CyberCP/public")
|
|
|
|
cwd = os.getcwd()
|
|
|
|
os.chdir('/usr/local/CyberCP')
|
|
|
|
command = '/usr/local/CyberPanel/bin/python manage.py collectstatic --noinput --clear'
|
|
Upgrade.executioner(command, 'Remove old static content', 0)
|
|
|
|
os.chdir(cwd)
|
|
|
|
shutil.move("/usr/local/CyberCP/static", "/usr/local/CyberCP/public/")
|
|
|
|
@staticmethod
|
|
def upgradeVersion():
|
|
try:
|
|
|
|
import django
|
|
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "CyberCP.settings")
|
|
django.setup()
|
|
from baseTemplate.models import version
|
|
|
|
vers = version.objects.get(pk=1)
|
|
vers.currentVersion = VERSION
|
|
vers.build = str(BUILD)
|
|
vers.save()
|
|
except:
|
|
pass
|
|
|
|
@staticmethod
|
|
def setupConnection(db=None):
|
|
try:
|
|
passFile = "/etc/cyberpanel/mysqlPassword"
|
|
|
|
f = open(passFile)
|
|
data = f.read()
|
|
password = data.split('\n', 1)[0]
|
|
|
|
if db == None:
|
|
conn = mysql.connect(user='root', passwd=password)
|
|
else:
|
|
try:
|
|
conn = mysql.connect(db=db, user='root', passwd=password)
|
|
except:
|
|
try:
|
|
conn = mysql.connect(host='127.0.0.1', port=3307, db=db, user='root', passwd=password)
|
|
except:
|
|
dbUser = settings.DATABASES['default']['USER']
|
|
password = settings.DATABASES['default']['PASSWORD']
|
|
host = settings.DATABASES['default']['HOST']
|
|
port = settings.DATABASES['default']['PORT']
|
|
|
|
if port == '':
|
|
conn = mysql.connect(host=host, port=3306, db=db, user=dbUser, passwd=password)
|
|
else:
|
|
conn = mysql.connect(host=host, port=int(port), db=db, user=dbUser, passwd=password)
|
|
|
|
cursor = conn.cursor()
|
|
return conn, cursor
|
|
|
|
except Exception as e:
|
|
ErrorSanitizer.log_error_securely(e, 'database_connection')
|
|
Upgrade.stdOut("Failed to establish database connection")
|
|
return 0, 0
|
|
|
|
@staticmethod
|
|
def applyLoginSystemMigrations():
|
|
try:
|
|
|
|
connection, cursor = Upgrade.setupConnection('cyberpanel')
|
|
|
|
try:
|
|
cursor.execute(
|
|
'CREATE TABLE `baseTemplate_cyberpanelcosmetic` (`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY, `MainDashboardCSS` longtext NOT NULL)')
|
|
except:
|
|
pass
|
|
|
|
# AI Scanner Tables
|
|
try:
|
|
cursor.execute('''
|
|
CREATE TABLE `ai_scanner_settings` (
|
|
`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
|
|
`admin_id` integer NOT NULL UNIQUE,
|
|
`api_key` varchar(255) DEFAULT NULL,
|
|
`balance` decimal(10,4) NOT NULL DEFAULT 0.0000,
|
|
`is_payment_configured` bool NOT NULL DEFAULT 0,
|
|
`created_at` datetime(6) NOT NULL,
|
|
`updated_at` datetime(6) NOT NULL,
|
|
KEY `ai_scanner_settings_admin_id_idx` (`admin_id`),
|
|
CONSTRAINT `ai_scanner_settings_admin_id_fk` FOREIGN KEY (`admin_id`)
|
|
REFERENCES `loginSystem_administrator` (`id`) ON DELETE CASCADE
|
|
)
|
|
''')
|
|
except:
|
|
pass
|
|
|
|
try:
|
|
cursor.execute('''
|
|
CREATE TABLE `ai_scanner_history` (
|
|
`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
|
|
`admin_id` integer NOT NULL,
|
|
`scan_id` varchar(100) NOT NULL UNIQUE,
|
|
`domain` varchar(255) NOT NULL,
|
|
`scan_type` varchar(20) NOT NULL DEFAULT 'full',
|
|
`status` varchar(20) NOT NULL DEFAULT 'pending',
|
|
`cost_usd` decimal(10,6) DEFAULT NULL,
|
|
`files_scanned` integer NOT NULL DEFAULT 0,
|
|
`issues_found` integer NOT NULL DEFAULT 0,
|
|
`findings_json` longtext DEFAULT NULL,
|
|
`summary_json` longtext DEFAULT NULL,
|
|
`error_message` longtext DEFAULT NULL,
|
|
`started_at` datetime(6) NOT NULL,
|
|
`completed_at` datetime(6) DEFAULT NULL,
|
|
KEY `ai_scanner_history_admin_id_idx` (`admin_id`),
|
|
KEY `ai_scanner_history_scan_id_idx` (`scan_id`),
|
|
KEY `ai_scanner_history_started_at_idx` (`started_at`),
|
|
CONSTRAINT `ai_scanner_history_admin_id_fk` FOREIGN KEY (`admin_id`)
|
|
REFERENCES `loginSystem_administrator` (`id`) ON DELETE CASCADE
|
|
)
|
|
''')
|
|
except:
|
|
pass
|
|
|
|
try:
|
|
cursor.execute('''
|
|
CREATE TABLE `ai_scanner_file_tokens` (
|
|
`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
|
|
`token` varchar(100) NOT NULL UNIQUE,
|
|
`scan_history_id` integer NOT NULL,
|
|
`domain` varchar(255) NOT NULL,
|
|
`wp_path` varchar(500) NOT NULL,
|
|
`expires_at` datetime(6) NOT NULL,
|
|
`created_at` datetime(6) NOT NULL,
|
|
`is_active` bool NOT NULL DEFAULT 1,
|
|
KEY `ai_scanner_file_tokens_scan_history_id_idx` (`scan_history_id`),
|
|
KEY `ai_scanner_file_tokens_token_idx` (`token`),
|
|
CONSTRAINT `ai_scanner_file_tokens_scan_history_id_fk` FOREIGN KEY (`scan_history_id`)
|
|
REFERENCES `ai_scanner_history` (`id`) ON DELETE CASCADE
|
|
)
|
|
''')
|
|
except:
|
|
pass
|
|
|
|
try:
|
|
cursor.execute('''
|
|
CREATE TABLE `ai_scanner_status_updates` (
|
|
`scan_id` varchar(100) NOT NULL PRIMARY KEY,
|
|
`phase` varchar(50) NOT NULL,
|
|
`progress` integer NOT NULL DEFAULT 0,
|
|
`current_file` longtext DEFAULT NULL,
|
|
`files_discovered` integer NOT NULL DEFAULT 0,
|
|
`files_scanned` integer NOT NULL DEFAULT 0,
|
|
`files_remaining` integer NOT NULL DEFAULT 0,
|
|
`threats_found` integer NOT NULL DEFAULT 0,
|
|
`critical_threats` integer NOT NULL DEFAULT 0,
|
|
`high_threats` integer NOT NULL DEFAULT 0,
|
|
`activity_description` longtext DEFAULT NULL,
|
|
`last_updated` datetime(6) NOT NULL,
|
|
`created_at` datetime(6) NOT NULL,
|
|
KEY `ai_scanner_status_updates_scan_id_last_updated_idx` (`scan_id`, `last_updated` DESC)
|
|
)
|
|
''')
|
|
except:
|
|
pass
|
|
|
|
# AI Scanner Scheduled Scans Tables
|
|
try:
|
|
cursor.execute('''
|
|
CREATE TABLE `ai_scanner_scheduled_scans` (
|
|
`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
|
|
`admin_id` integer NOT NULL,
|
|
`name` varchar(200) NOT NULL,
|
|
`domains` longtext NOT NULL,
|
|
`frequency` varchar(20) NOT NULL DEFAULT 'weekly',
|
|
`scan_type` varchar(20) NOT NULL DEFAULT 'full',
|
|
`time_of_day` time NOT NULL,
|
|
`day_of_week` integer DEFAULT NULL,
|
|
`day_of_month` integer DEFAULT NULL,
|
|
`status` varchar(20) NOT NULL DEFAULT 'active',
|
|
`last_run` datetime(6) DEFAULT NULL,
|
|
`next_run` datetime(6) DEFAULT NULL,
|
|
`created_at` datetime(6) NOT NULL,
|
|
`updated_at` datetime(6) NOT NULL,
|
|
`email_notifications` bool NOT NULL DEFAULT 1,
|
|
`notification_emails` longtext NOT NULL DEFAULT '',
|
|
`notify_on_threats` bool NOT NULL DEFAULT 1,
|
|
`notify_on_completion` bool NOT NULL DEFAULT 0,
|
|
`notify_on_failure` bool NOT NULL DEFAULT 1,
|
|
KEY `ai_scanner_scheduled_scans_admin_id_idx` (`admin_id`),
|
|
KEY `ai_scanner_scheduled_scans_status_next_run_idx` (`status`, `next_run`),
|
|
CONSTRAINT `ai_scanner_scheduled_scans_admin_id_fk` FOREIGN KEY (`admin_id`)
|
|
REFERENCES `loginSystem_administrator` (`id`) ON DELETE CASCADE
|
|
)
|
|
''')
|
|
except:
|
|
pass
|
|
|
|
try:
|
|
cursor.execute('''
|
|
CREATE TABLE `ai_scanner_scheduled_executions` (
|
|
`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
|
|
`scheduled_scan_id` integer NOT NULL,
|
|
`execution_time` datetime(6) NOT NULL,
|
|
`status` varchar(20) NOT NULL DEFAULT 'pending',
|
|
`domains_scanned` longtext NOT NULL DEFAULT '',
|
|
`total_scans` integer NOT NULL DEFAULT 0,
|
|
`successful_scans` integer NOT NULL DEFAULT 0,
|
|
`failed_scans` integer NOT NULL DEFAULT 0,
|
|
`total_cost` decimal(10,6) NOT NULL DEFAULT 0.000000,
|
|
`scan_ids` longtext NOT NULL DEFAULT '',
|
|
`error_message` longtext DEFAULT NULL,
|
|
`started_at` datetime(6) DEFAULT NULL,
|
|
`completed_at` datetime(6) DEFAULT NULL,
|
|
KEY `ai_scanner_scheduled_executions_scheduled_scan_id_idx` (`scheduled_scan_id`),
|
|
KEY `ai_scanner_scheduled_executions_execution_time_idx` (`execution_time` DESC),
|
|
CONSTRAINT `ai_scanner_scheduled_executions_scheduled_scan_id_fk` FOREIGN KEY (`scheduled_scan_id`)
|
|
REFERENCES `ai_scanner_scheduled_scans` (`id`) ON DELETE CASCADE
|
|
)
|
|
''')
|
|
except:
|
|
pass
|
|
|
|
try:
|
|
cursor.execute(
|
|
'CREATE TABLE `loginSystem_acl` (`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY, `name` varchar(50) NOT NULL UNIQUE, `adminStatus` integer NOT NULL DEFAULT 0, `versionManagement` integer NOT NULL DEFAULT 0, `createNewUser` integer NOT NULL DEFAULT 0, `deleteUser` integer NOT NULL DEFAULT 0, `resellerCenter` integer NOT NULL DEFAULT 0, `changeUserACL` integer NOT NULL DEFAULT 0, `createWebsite` integer NOT NULL DEFAULT 0, `modifyWebsite` integer NOT NULL DEFAULT 0, `suspendWebsite` integer NOT NULL DEFAULT 0, `deleteWebsite` integer NOT NULL DEFAULT 0, `createPackage` integer NOT NULL DEFAULT 0, `deletePackage` integer NOT NULL DEFAULT 0, `modifyPackage` integer NOT NULL DEFAULT 0, `createDatabase` integer NOT NULL DEFAULT 0, `deleteDatabase` integer NOT NULL DEFAULT 0, `listDatabases` integer NOT NULL DEFAULT 0, `createNameServer` integer NOT NULL DEFAULT 0, `createDNSZone` integer NOT NULL DEFAULT 0, `deleteZone` integer NOT NULL DEFAULT 0, `addDeleteRecords` integer NOT NULL DEFAULT 0, `createEmail` integer NOT NULL DEFAULT 0, `deleteEmail` integer NOT NULL DEFAULT 0, `emailForwarding` integer NOT NULL DEFAULT 0, `changeEmailPassword` integer NOT NULL DEFAULT 0, `dkimManager` integer NOT NULL DEFAULT 0, `createFTPAccount` integer NOT NULL DEFAULT 0, `deleteFTPAccount` integer NOT NULL DEFAULT 0, `listFTPAccounts` integer NOT NULL DEFAULT 0, `createBackup` integer NOT NULL DEFAULT 0, `restoreBackup` integer NOT NULL DEFAULT 0, `addDeleteDestinations` integer NOT NULL DEFAULT 0, `scheduleBackups` integer NOT NULL DEFAULT 0, `remoteBackups` integer NOT NULL DEFAULT 0, `manageSSL` integer NOT NULL DEFAULT 0, `hostnameSSL` integer NOT NULL DEFAULT 0, `mailServerSSL` integer NOT NULL DEFAULT 0)')
|
|
except:
|
|
pass
|
|
|
|
try:
|
|
cursor.execute('ALTER TABLE loginSystem_administrator ADD token varchar(500)')
|
|
except:
|
|
pass
|
|
|
|
try:
|
|
cursor.execute("ALTER TABLE loginSystem_administrator ADD secretKey varchar(50) DEFAULT 'None'")
|
|
except:
|
|
pass
|
|
|
|
try:
|
|
cursor.execute('alter table databases_databases drop index dbUser;')
|
|
except:
|
|
pass
|
|
|
|
try:
|
|
cursor.execute("ALTER TABLE loginSystem_administrator ADD state varchar(15) DEFAULT 'ACTIVE'")
|
|
except:
|
|
pass
|
|
|
|
try:
|
|
cursor.execute('ALTER TABLE loginSystem_administrator ADD securityLevel integer DEFAULT 1')
|
|
except:
|
|
pass
|
|
|
|
try:
|
|
cursor.execute('ALTER TABLE loginSystem_administrator ADD defaultSite integer DEFAULT 0')
|
|
except:
|
|
pass
|
|
|
|
try:
|
|
cursor.execute('ALTER TABLE loginSystem_administrator ADD twoFA integer DEFAULT 0')
|
|
except:
|
|
pass
|
|
|
|
try:
|
|
cursor.execute('ALTER TABLE loginSystem_administrator ADD api integer')
|
|
except:
|
|
pass
|
|
|
|
try:
|
|
cursor.execute('ALTER TABLE loginSystem_administrator ADD acl_id integer')
|
|
except:
|
|
pass
|
|
try:
|
|
cursor.execute(
|
|
'ALTER TABLE loginSystem_administrator ADD FOREIGN KEY (acl_id) REFERENCES loginSystem_acl(id)')
|
|
except:
|
|
pass
|
|
|
|
try:
|
|
cursor.execute("insert into loginSystem_acl (id, name, adminStatus) values (1,'admin',1)")
|
|
except:
|
|
pass
|
|
|
|
try:
|
|
cursor.execute(
|
|
"insert into loginSystem_acl (id, name, adminStatus, createNewUser, deleteUser, createWebsite, resellerCenter, modifyWebsite, suspendWebsite, deleteWebsite, createPackage, deletePackage, modifyPackage, createNameServer, restoreBackup) values (2,'reseller',0,1,1,1,1,1,1,1,1,1,1,1,1)")
|
|
except:
|
|
pass
|
|
try:
|
|
cursor.execute(
|
|
"insert into loginSystem_acl (id, name, createDatabase, deleteDatabase, listDatabases, createDNSZone, deleteZone, addDeleteRecords, createEmail, deleteEmail, emailForwarding, changeEmailPassword, dkimManager, createFTPAccount, deleteFTPAccount, listFTPAccounts, createBackup, manageSSL) values (3,'user', 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1)")
|
|
except:
|
|
pass
|
|
|
|
try:
|
|
cursor.execute("UPDATE loginSystem_administrator SET acl_id = 1 where userName = 'admin'")
|
|
except:
|
|
pass
|
|
|
|
try:
|
|
cursor.execute('ALTER TABLE loginSystem_acl ADD config longtext')
|
|
except:
|
|
pass
|
|
|
|
try:
|
|
cursor.execute("UPDATE loginSystem_acl SET config = '%s' where name = 'admin'" % (Upgrade.AdminACL))
|
|
except Exception as e:
|
|
ErrorSanitizer.log_error_securely(e, 'applyLoginSystemMigrations')
|
|
try:
|
|
import sleep
|
|
except:
|
|
from time import sleep
|
|
from time import sleep
|
|
sleep(10)
|
|
|
|
try:
|
|
cursor.execute(
|
|
"UPDATE loginSystem_acl SET config = '%s' where name = 'reseller'" % (Upgrade.ResellerACL))
|
|
except:
|
|
pass
|
|
|
|
try:
|
|
cursor.execute("UPDATE loginSystem_acl SET config = '%s' where name = 'user'" % (Upgrade.UserACL))
|
|
except:
|
|
pass
|
|
|
|
try:
|
|
cursor.execute("alter table loginSystem_administrator drop initUserAccountsLimit")
|
|
except:
|
|
pass
|
|
|
|
try:
|
|
cursor.execute(
|
|
"CREATE TABLE `websiteFunctions_aliasdomains` (`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY, `aliasDomain` varchar(75) NOT NULL)")
|
|
except:
|
|
pass
|
|
try:
|
|
cursor.execute("ALTER TABLE `websiteFunctions_aliasdomains` ADD COLUMN `master_id` integer NOT NULL")
|
|
except:
|
|
pass
|
|
try:
|
|
cursor.execute(
|
|
"ALTER TABLE `websiteFunctions_aliasdomains` ADD CONSTRAINT `websiteFunctions_ali_master_id_726c433d_fk_websiteFu` FOREIGN KEY (`master_id`) REFERENCES `websiteFunctions_websites` (`id`)")
|
|
except:
|
|
pass
|
|
|
|
try:
|
|
cursor.execute('ALTER TABLE websiteFunctions_websites ADD config longtext')
|
|
except:
|
|
pass
|
|
|
|
try:
|
|
cursor.execute("ALTER TABLE websiteFunctions_websites MODIFY externalApp varchar(30)")
|
|
except:
|
|
pass
|
|
|
|
try:
|
|
cursor.execute("ALTER TABLE emailMarketing_smtphosts MODIFY userName varchar(200)")
|
|
except:
|
|
pass
|
|
|
|
try:
|
|
cursor.execute("ALTER TABLE emailMarketing_smtphosts MODIFY password varchar(200)")
|
|
except:
|
|
pass
|
|
|
|
try:
|
|
cursor.execute("ALTER TABLE websiteFunctions_backups MODIFY fileName varchar(200)")
|
|
except:
|
|
pass
|
|
|
|
try:
|
|
cursor.execute("ALTER TABLE loginSystem_acl ADD COLUMN listUsers INT DEFAULT 0;")
|
|
except:
|
|
pass
|
|
|
|
try:
|
|
cursor.execute("ALTER TABLE loginSystem_acl ADD COLUMN listEmails INT DEFAULT 1;")
|
|
except:
|
|
pass
|
|
|
|
try:
|
|
cursor.execute("ALTER TABLE loginSystem_acl ADD COLUMN listPackages INT DEFAULT 0;")
|
|
except:
|
|
pass
|
|
|
|
query = """CREATE TABLE `websiteFunctions_normalbackupdests` (
|
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
`name` varchar(25) NOT NULL,
|
|
`config` longtext NOT NULL,
|
|
PRIMARY KEY (`id`)
|
|
)"""
|
|
try:
|
|
cursor.execute(query)
|
|
except:
|
|
pass
|
|
|
|
query = """CREATE TABLE `cloudAPI_wpdeployments` (
|
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
`config` longtext NOT NULL,
|
|
`owner_id` int(11) NOT NULL,
|
|
PRIMARY KEY (`id`),
|
|
KEY `cloudAPI_wpdeploymen_owner_id_506ddf01_fk_websiteFu` (`owner_id`),
|
|
CONSTRAINT `cloudAPI_wpdeploymen_owner_id_506ddf01_fk_websiteFu` FOREIGN KEY (`owner_id`) REFERENCES `websiteFunctions_websites` (`id`)
|
|
)"""
|
|
|
|
try:
|
|
cursor.execute(query)
|
|
except:
|
|
pass
|
|
|
|
query = """CREATE TABLE `websiteFunctions_normalbackupjobs` (
|
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
`name` varchar(25) NOT NULL,
|
|
`config` longtext NOT NULL,
|
|
`owner_id` int(11) NOT NULL,
|
|
PRIMARY KEY (`id`),
|
|
KEY `websiteFunctions_nor_owner_id_3a7a13db_fk_websiteFu` (`owner_id`),
|
|
CONSTRAINT `websiteFunctions_nor_owner_id_3a7a13db_fk_websiteFu` FOREIGN KEY (`owner_id`) REFERENCES `websiteFunctions_normalbackupdests` (`id`)
|
|
)"""
|
|
|
|
try:
|
|
cursor.execute(query)
|
|
except:
|
|
pass
|
|
|
|
query = """CREATE TABLE `websiteFunctions_normalbackupsites` (
|
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
`domain_id` int(11) NOT NULL,
|
|
`owner_id` int(11) NOT NULL,
|
|
PRIMARY KEY (`id`),
|
|
KEY `websiteFunctions_nor_domain_id_c03362bc_fk_websiteFu` (`domain_id`),
|
|
KEY `websiteFunctions_nor_owner_id_c6ece6cc_fk_websiteFu` (`owner_id`),
|
|
CONSTRAINT `websiteFunctions_nor_domain_id_c03362bc_fk_websiteFu` FOREIGN KEY (`domain_id`) REFERENCES `websiteFunctions_websites` (`id`),
|
|
CONSTRAINT `websiteFunctions_nor_owner_id_c6ece6cc_fk_websiteFu` FOREIGN KEY (`owner_id`) REFERENCES `websiteFunctions_normalbackupjobs` (`id`)
|
|
)"""
|
|
|
|
try:
|
|
cursor.execute(query)
|
|
except:
|
|
pass
|
|
|
|
query = """CREATE TABLE `websiteFunctions_normalbackupjoblogs` (
|
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
`status` int(11) NOT NULL,
|
|
`message` longtext NOT NULL,
|
|
`owner_id` int(11) NOT NULL,
|
|
PRIMARY KEY (`id`),
|
|
KEY `websiteFunctions_nor_owner_id_69403e73_fk_websiteFu` (`owner_id`),
|
|
CONSTRAINT `websiteFunctions_nor_owner_id_69403e73_fk_websiteFu` FOREIGN KEY (`owner_id`) REFERENCES `websiteFunctions_normalbackupjobs` (`id`)
|
|
)"""
|
|
|
|
try:
|
|
cursor.execute(query)
|
|
except:
|
|
pass
|
|
|
|
try:
|
|
cursor.execute('ALTER TABLE e_users ADD DiskUsage varchar(200)')
|
|
except:
|
|
pass
|
|
|
|
try:
|
|
cursor.execute(
|
|
'CREATE TABLE `websiteFunctions_wpplugins` (`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY, `Name` varchar(255) NOT NULL, `config` longtext NOT NULL, `owner_id` integer NOT NULL)')
|
|
except:
|
|
pass
|
|
|
|
try:
|
|
cursor.execute(
|
|
'ALTER TABLE `websiteFunctions_wpplugins` ADD CONSTRAINT `websiteFunctions_wpp_owner_id_493a02c7_fk_loginSyst` FOREIGN KEY (`owner_id`) REFERENCES `loginSystem_administrator` (`id`)')
|
|
except:
|
|
pass
|
|
|
|
try:
|
|
cursor.execute(
|
|
'CREATE TABLE `websiteFunctions_wpsites` (`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY, `title` varchar(255) NOT NULL, `path` varchar(255) NOT NULL, `FinalURL` varchar(255) NOT NULL, `AutoUpdates` varchar(100) NOT NULL, `PluginUpdates` varchar(15) NOT NULL, `ThemeUpdates` varchar(15) NOT NULL, `date` datetime(6) NOT NULL, `WPLockState` integer NOT NULL, `owner_id` integer NOT NULL)')
|
|
except:
|
|
pass
|
|
|
|
try:
|
|
cursor.execute(
|
|
'ALTER TABLE `websiteFunctions_wpsites` ADD CONSTRAINT `websiteFunctions_wps_owner_id_6d67df2a_fk_websiteFu` FOREIGN KEY (`owner_id`) REFERENCES `websiteFunctions_websites` (`id`)')
|
|
except:
|
|
pass
|
|
|
|
try:
|
|
cursor.execute(
|
|
'CREATE TABLE `websiteFunctions_wpstaging` (`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY, `owner_id` integer NOT NULL, `wpsite_id` integer NOT NULL)')
|
|
except:
|
|
pass
|
|
|
|
try:
|
|
cursor.execute(
|
|
'ALTER TABLE `websiteFunctions_wpstaging` ADD CONSTRAINT `websiteFunctions_wps_owner_id_543d8aec_fk_websiteFu` FOREIGN KEY (`owner_id`) REFERENCES `websiteFunctions_wpsites` (`id`);')
|
|
except:
|
|
pass
|
|
|
|
try:
|
|
cursor.execute(
|
|
'ALTER TABLE `websiteFunctions_wpstaging` ADD CONSTRAINT `websiteFunctions_wps_wpsite_id_82843593_fk_websiteFu` FOREIGN KEY (`wpsite_id`) REFERENCES `websiteFunctions_wpsites` (`id`)')
|
|
except:
|
|
pass
|
|
|
|
try:
|
|
cursor.execute(
|
|
"CREATE TABLE `websiteFunctions_wpsitesbackup` (`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY, `WPSiteID` integer NOT NULL, `WebsiteID` integer NOT NULL, `config` longtext NOT NULL, `owner_id` integer NOT NULL); ")
|
|
except:
|
|
pass
|
|
|
|
try:
|
|
cursor.execute(
|
|
"ALTER TABLE `websiteFunctions_wpsitesbackup` ADD CONSTRAINT `websiteFunctions_wps_owner_id_8a8dd0c5_fk_loginSyst` FOREIGN KEY (`owner_id`) REFERENCES `loginSystem_administrator` (`id`); ")
|
|
except:
|
|
pass
|
|
|
|
query = """CREATE TABLE `websiteFunctions_remotebackupconfig` (
|
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
`configtype` varchar(255) NOT NULL,
|
|
`config` longtext NOT NULL,
|
|
`owner_id` int(11) NOT NULL,
|
|
PRIMARY KEY (`id`)
|
|
)"""
|
|
try:
|
|
cursor.execute(query)
|
|
except:
|
|
pass
|
|
|
|
query = """CREATE TABLE `websiteFunctions_remotebackupschedule` (
|
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
`Name` varchar(255) NOT NULL,
|
|
`timeintervel` varchar(200) NOT NULL,
|
|
`fileretention` varchar(200) NOT NULL,
|
|
`lastrun` varchar(200) NOT NULL,
|
|
`config` longtext NOT NULL,
|
|
`RemoteBackupConfig_id` int(11) NOT NULL,
|
|
PRIMARY KEY (`id`),
|
|
KEY `websiteFunctions_rem_RemoteBackupConfig_i_224c46fb_fk_websiteFu` (`RemoteBackupConfig_id`),
|
|
CONSTRAINT `websiteFunctions_rem_RemoteBackupConfig_i_224c46fb_fk_websiteFu` FOREIGN KEY (`RemoteBackupConfig_id`) REFERENCES `websiteFunctions_remotebackupconfig` (`id`)
|
|
)"""
|
|
try:
|
|
cursor.execute(query)
|
|
except:
|
|
pass
|
|
|
|
query = """CREATE TABLE `websiteFunctions_remotebackupsites` (
|
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
`WPsites` int(11) DEFAULT NULL,
|
|
`database` int(11) DEFAULT NULL,
|
|
`owner_id` int(11) NOT NULL,
|
|
PRIMARY KEY (`id`),
|
|
KEY `websiteFunctions_rem_owner_id_d6c4475a_fk_websiteFu` (`owner_id`),
|
|
CONSTRAINT `websiteFunctions_rem_owner_id_d6c4475a_fk_websiteFu` FOREIGN KEY (`owner_id`) REFERENCES `websiteFunctions_remotebackupschedule` (`id`)
|
|
)"""
|
|
try:
|
|
cursor.execute(query)
|
|
except:
|
|
pass
|
|
|
|
query = """
|
|
CREATE TABLE `websiteFunctions_backupsv2` (`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY, `fileName` varchar(255) NOT NULL, `status` integer NOT NULL, `timeStamp` varchar(255) NOT NULL, `BasePath` longtext NOT NULL, `website_id` integer NOT NULL);
|
|
"""
|
|
try:
|
|
cursor.execute(query)
|
|
except:
|
|
pass
|
|
|
|
query = "ALTER TABLE `websiteFunctions_backupsv2` ADD CONSTRAINT `websiteFunctions_bac_website_id_3a777e68_fk_websiteFu` FOREIGN KEY (`website_id`) REFERENCES `websiteFunctions_websites` (`id`);"
|
|
|
|
try:
|
|
cursor.execute(query)
|
|
except:
|
|
pass
|
|
|
|
query = "ALTER TABLE `websiteFunctions_backupslogsv2` ADD CONSTRAINT `websiteFunctions_bac_owner_id_9e884ff9_fk_websiteFu` FOREIGN KEY (`owner_id`) REFERENCES `websiteFunctions_backupsv2` (`id`);"
|
|
|
|
try:
|
|
cursor.execute(query)
|
|
except:
|
|
pass
|
|
|
|
query = "CREATE TABLE `websiteFunctions_backupslogsv2` (`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY, `timeStamp` varchar(255) NOT NULL, `message` longtext NOT NULL, `owner_id` integer NOT NULL);"
|
|
|
|
try:
|
|
cursor.execute(query)
|
|
except:
|
|
pass
|
|
|
|
query = "ALTER TABLE `websiteFunctions_backupslogsv2` ADD CONSTRAINT `websiteFunctions_bac_owner_id_9e884ff9_fk_websiteFu` FOREIGN KEY (`owner_id`) REFERENCES `websiteFunctions_backupsv2` (`id`);"
|
|
|
|
try:
|
|
cursor.execute(query)
|
|
except:
|
|
pass
|
|
|
|
try:
|
|
cursor.execute("ALTER TABLE websiteFunctions_websites ADD COLUMN BackupLock INT DEFAULT 0;")
|
|
except:
|
|
pass
|
|
|
|
### update ftp issue for ubuntu 22
|
|
|
|
try:
|
|
cursor.execute(
|
|
'ALTER TABLE `users` CHANGE `Password` `Password` VARCHAR(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL; ')
|
|
except:
|
|
pass
|
|
|
|
query = "CREATE TABLE `IncBackups_oneclickbackups` (`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY, `planName` varchar(100) NOT NULL, `months` varchar(100) NOT NULL, `price` varchar(100) NOT NULL, `customer` varchar(255) NOT NULL, `subscription` varchar(255) NOT NULL UNIQUE, `sftpUser` varchar(100) NOT NULL, `config` longtext NOT NULL, `date` datetime(6) NOT NULL, `state` integer NOT NULL, `owner_id` integer NOT NULL);"
|
|
try:
|
|
cursor.execute(query)
|
|
except:
|
|
pass
|
|
|
|
query = 'ALTER TABLE `IncBackups_oneclickbackups` ADD CONSTRAINT `IncBackups_oneclickb_owner_id_7b4250a4_fk_loginSyst` FOREIGN KEY (`owner_id`) REFERENCES `loginSystem_administrator` (`id`);'
|
|
try:
|
|
cursor.execute(query)
|
|
except:
|
|
pass
|
|
|
|
if Upgrade.FindOperatingSytem() == Ubuntu22 or Upgrade.FindOperatingSytem() == Ubuntu24 or Upgrade.FindOperatingSytem() == Debian11 or Upgrade.FindOperatingSytem() == Debian12 or Upgrade.FindOperatingSytem() == Debian13:
|
|
### If ftp not installed then upgrade will fail so this command should not do exit
|
|
|
|
command = "sed -i 's/MYSQLCrypt md5/MYSQLCrypt crypt/g' /etc/pure-ftpd/db/mysql.conf"
|
|
Upgrade.executioner(command, command, 0)
|
|
|
|
command = "systemctl restart pure-ftpd-mysql.service"
|
|
Upgrade.executioner(command, command, 0)
|
|
|
|
try:
|
|
clAPVersion = Upgrade.FetchCloudLinuxAlmaVersionVersion()
|
|
if isinstance(clAPVersion, str) and '-' in clAPVersion:
|
|
type = clAPVersion.split('-')[0]
|
|
version = int(clAPVersion.split('-')[1])
|
|
|
|
if type == 'al' and version >= 90:
|
|
command = "sed -i 's/MYSQLCrypt md5/MYSQLCrypt crypt/g' /etc/pure-ftpd/pureftpd-mysql.conf"
|
|
Upgrade.executioner(command, command, 0)
|
|
except:
|
|
pass
|
|
|
|
try:
|
|
connection.close()
|
|
except:
|
|
pass
|
|
|
|
except OSError as msg:
|
|
Upgrade.stdOut(str(msg) + " [applyLoginSystemMigrations]")
|
|
|
|
@staticmethod
|
|
def s3BackupMigrations():
|
|
try:
|
|
|
|
connection, cursor = Upgrade.setupConnection('cyberpanel')
|
|
|
|
query = """CREATE TABLE `s3Backups_backupplan` (
|
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
`name` varchar(50) NOT NULL,
|
|
`bucket` varchar(50) NOT NULL,
|
|
`freq` varchar(50) NOT NULL,
|
|
`retention` int(11) NOT NULL,
|
|
`type` varchar(5) NOT NULL,
|
|
`lastRun` varchar(50) NOT NULL,
|
|
`owner_id` int(11) NOT NULL,
|
|
PRIMARY KEY (`id`),
|
|
UNIQUE KEY `name` (`name`),
|
|
KEY `s3Backups_backupplan_owner_id_7d058ced_fk_loginSyst` (`owner_id`),
|
|
CONSTRAINT `s3Backups_backupplan_owner_id_7d058ced_fk_loginSyst` FOREIGN KEY (`owner_id`) REFERENCES `loginSystem_administrator` (`id`)
|
|
)"""
|
|
|
|
try:
|
|
cursor.execute(query)
|
|
except:
|
|
pass
|
|
|
|
try:
|
|
cursor.execute('ALTER TABLE s3Backups_backupplan ADD config longtext')
|
|
except:
|
|
pass
|
|
|
|
query = """CREATE TABLE `s3Backups_websitesinplan` (
|
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
`domain` varchar(100) NOT NULL,
|
|
`owner_id` int(11) NOT NULL,
|
|
PRIMARY KEY (`id`),
|
|
KEY `s3Backups_websitesin_owner_id_0e9a4fe3_fk_s3Backups` (`owner_id`),
|
|
CONSTRAINT `s3Backups_websitesin_owner_id_0e9a4fe3_fk_s3Backups` FOREIGN KEY (`owner_id`) REFERENCES `s3Backups_backupplan` (`id`)
|
|
)"""
|
|
|
|
try:
|
|
cursor.execute(query)
|
|
except:
|
|
pass
|
|
|
|
query = """CREATE TABLE `s3Backups_backuplogs` (
|
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
`timeStamp` varchar(200) NOT NULL,
|
|
`level` varchar(5) NOT NULL,
|
|
`msg` varchar(500) NOT NULL,
|
|
`owner_id` int(11) NOT NULL,
|
|
PRIMARY KEY (`id`),
|
|
KEY `s3Backups_backuplogs_owner_id_7b4653af_fk_s3Backups` (`owner_id`),
|
|
CONSTRAINT `s3Backups_backuplogs_owner_id_7b4653af_fk_s3Backups` FOREIGN KEY (`owner_id`) REFERENCES `s3Backups_backupplan` (`id`)
|
|
)"""
|
|
|
|
try:
|
|
cursor.execute(query)
|
|
except:
|
|
pass
|
|
|
|
query = """CREATE TABLE `s3Backups_backupplando` (
|
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
`name` varchar(50) NOT NULL,
|
|
`bucket` varchar(50) NOT NULL,
|
|
`freq` varchar(50) NOT NULL,
|
|
`retention` int(11) NOT NULL,
|
|
`type` varchar(5) NOT NULL,
|
|
`region` varchar(5) NOT NULL,
|
|
`lastRun` varchar(50) NOT NULL,
|
|
`owner_id` int(11) NOT NULL,
|
|
PRIMARY KEY (`id`),
|
|
UNIQUE KEY `name` (`name`),
|
|
KEY `s3Backups_backupplan_owner_id_1a3ec86d_fk_loginSyst` (`owner_id`),
|
|
CONSTRAINT `s3Backups_backupplan_owner_id_1a3ec86d_fk_loginSyst` FOREIGN KEY (`owner_id`) REFERENCES `loginSystem_administrator` (`id`)
|
|
)"""
|
|
|
|
try:
|
|
cursor.execute(query)
|
|
except:
|
|
pass
|
|
|
|
query = """CREATE TABLE `s3Backups_websitesinplando` (
|
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
`domain` varchar(100) NOT NULL,
|
|
`owner_id` int(11) NOT NULL,
|
|
PRIMARY KEY (`id`),
|
|
KEY `s3Backups_websitesin_owner_id_cef3ea04_fk_s3Backups` (`owner_id`),
|
|
CONSTRAINT `s3Backups_websitesin_owner_id_cef3ea04_fk_s3Backups` FOREIGN KEY (`owner_id`) REFERENCES `s3Backups_backupplando` (`id`)
|
|
)"""
|
|
|
|
try:
|
|
cursor.execute(query)
|
|
except:
|
|
pass
|
|
|
|
query = """CREATE TABLE `s3Backups_backuplogsdo` (
|
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
`timeStamp` varchar(200) NOT NULL,
|
|
`level` varchar(5) NOT NULL,
|
|
`msg` varchar(500) NOT NULL,
|
|
`owner_id` int(11) NOT NULL,
|
|
PRIMARY KEY (`id`),
|
|
KEY `s3Backups_backuplogs_owner_id_c7cb5872_fk_s3Backups` (`owner_id`),
|
|
CONSTRAINT `s3Backups_backuplogs_owner_id_c7cb5872_fk_s3Backups` FOREIGN KEY (`owner_id`) REFERENCES `s3Backups_backupplando` (`id`)
|
|
)"""
|
|
|
|
try:
|
|
cursor.execute(query)
|
|
except:
|
|
pass
|
|
|
|
##
|
|
|
|
query = """CREATE TABLE `s3Backups_minionodes` (
|
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
`endPointURL` varchar(200) NOT NULL,
|
|
`accessKey` varchar(200) NOT NULL,
|
|
`secretKey` varchar(200) NOT NULL,
|
|
`owner_id` int(11) NOT NULL,
|
|
PRIMARY KEY (`id`),
|
|
UNIQUE KEY `endPointURL` (`endPointURL`),
|
|
UNIQUE KEY `accessKey` (`accessKey`),
|
|
KEY `s3Backups_minionodes_owner_id_e50993d9_fk_loginSyst` (`owner_id`),
|
|
CONSTRAINT `s3Backups_minionodes_owner_id_e50993d9_fk_loginSyst` FOREIGN KEY (`owner_id`) REFERENCES `loginSystem_administrator` (`id`)
|
|
)"""
|
|
|
|
try:
|
|
cursor.execute(query)
|
|
except:
|
|
pass
|
|
|
|
query = """CREATE TABLE `s3Backups_backupplanminio` (
|
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
`name` varchar(50) NOT NULL,
|
|
`freq` varchar(50) NOT NULL,
|
|
`retention` int(11) NOT NULL,
|
|
`lastRun` varchar(50) NOT NULL,
|
|
`minioNode_id` int(11) NOT NULL,
|
|
`owner_id` int(11) NOT NULL,
|
|
PRIMARY KEY (`id`),
|
|
UNIQUE KEY `name` (`name`),
|
|
KEY `s3Backups_backupplan_minioNode_id_a4eaf917_fk_s3Backups` (`minioNode_id`),
|
|
KEY `s3Backups_backupplan_owner_id_d6830e67_fk_loginSyst` (`owner_id`),
|
|
CONSTRAINT `s3Backups_backupplan_minioNode_id_a4eaf917_fk_s3Backups` FOREIGN KEY (`minioNode_id`) REFERENCES `s3Backups_minionodes` (`id`),
|
|
CONSTRAINT `s3Backups_backupplan_owner_id_d6830e67_fk_loginSyst` FOREIGN KEY (`owner_id`) REFERENCES `loginSystem_administrator` (`id`)
|
|
)"""
|
|
|
|
try:
|
|
cursor.execute(query)
|
|
except:
|
|
pass
|
|
|
|
query = """CREATE TABLE `s3Backups_websitesinplanminio` (
|
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
`domain` varchar(100) NOT NULL,
|
|
`owner_id` int(11) NOT NULL,
|
|
PRIMARY KEY (`id`),
|
|
KEY `s3Backups_websitesin_owner_id_224ce049_fk_s3Backups` (`owner_id`),
|
|
CONSTRAINT `s3Backups_websitesin_owner_id_224ce049_fk_s3Backups` FOREIGN KEY (`owner_id`) REFERENCES `s3Backups_backupplanminio` (`id`)
|
|
)"""
|
|
|
|
try:
|
|
cursor.execute(query)
|
|
except:
|
|
pass
|
|
|
|
query = """CREATE TABLE `s3Backups_backuplogsminio` (
|
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
`timeStamp` varchar(200) NOT NULL,
|
|
`level` varchar(5) NOT NULL,
|
|
`msg` varchar(500) NOT NULL,
|
|
`owner_id` int(11) NOT NULL,
|
|
PRIMARY KEY (`id`),
|
|
KEY `s3Backups_backuplogs_owner_id_f19e1736_fk_s3Backups` (`owner_id`),
|
|
CONSTRAINT `s3Backups_backuplogs_owner_id_f19e1736_fk_s3Backups` FOREIGN KEY (`owner_id`) REFERENCES `s3Backups_backupplanminio` (`id`)
|
|
)"""
|
|
|
|
try:
|
|
cursor.execute(query)
|
|
except:
|
|
pass
|
|
|
|
try:
|
|
connection.close()
|
|
except:
|
|
pass
|
|
|
|
except OSError as msg:
|
|
Upgrade.stdOut(str(msg) + " [applyLoginSystemMigrations]")
|
|
|
|
@staticmethod
|
|
def mailServerMigrations():
|
|
try:
|
|
connection, cursor = Upgrade.setupConnection('cyberpanel')
|
|
|
|
try:
|
|
cursor.execute(
|
|
'ALTER TABLE `e_domains` ADD COLUMN `childOwner_id` integer')
|
|
except:
|
|
pass
|
|
|
|
try:
|
|
cursor.execute(
|
|
'ALTER TABLE e_users ADD mail varchar(200)')
|
|
except:
|
|
pass
|
|
|
|
try:
|
|
cursor.execute(
|
|
'ALTER TABLE e_users MODIFY password varchar(200)')
|
|
except:
|
|
pass
|
|
|
|
try:
|
|
cursor.execute(
|
|
'ALTER TABLE e_forwardings DROP PRIMARY KEY;ALTER TABLE e_forwardings ADD id INT AUTO_INCREMENT PRIMARY KEY')
|
|
except:
|
|
pass
|
|
|
|
query = """CREATE TABLE `emailPremium_domainlimits` (
|
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
`limitStatus` int(11) NOT NULL,
|
|
`monthlyLimit` int(11) NOT NULL,
|
|
`monthlyUsed` int(11) NOT NULL,
|
|
`domain_id` varchar(50) NOT NULL,
|
|
PRIMARY KEY (`id`),
|
|
KEY `emailPremium_domainlimits_domain_id_303ab297_fk_e_domains_domain` (`domain_id`),
|
|
CONSTRAINT `emailPremium_domainlimits_domain_id_303ab297_fk_e_domains_domain` FOREIGN KEY (`domain_id`) REFERENCES `e_domains` (`domain`)
|
|
)"""
|
|
try:
|
|
cursor.execute(query)
|
|
except:
|
|
pass
|
|
|
|
query = """CREATE TABLE `emailPremium_emaillimits` (
|
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
`limitStatus` int(11) NOT NULL,
|
|
`monthlyLimits` int(11) NOT NULL,
|
|
`monthlyUsed` int(11) NOT NULL,
|
|
`hourlyLimit` int(11) NOT NULL,
|
|
`hourlyUsed` int(11) NOT NULL,
|
|
`emailLogs` int(11) NOT NULL,
|
|
`email_id` varchar(80) NOT NULL,
|
|
PRIMARY KEY (`id`),
|
|
KEY `emailPremium_emaillimits_email_id_1c111df5_fk_e_users_email` (`email_id`),
|
|
CONSTRAINT `emailPremium_emaillimits_email_id_1c111df5_fk_e_users_email` FOREIGN KEY (`email_id`) REFERENCES `e_users` (`email`)
|
|
)"""
|
|
try:
|
|
cursor.execute(query)
|
|
except:
|
|
pass
|
|
|
|
query = """CREATE TABLE `emailPremium_emaillogs` (
|
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
`destination` varchar(200) NOT NULL,
|
|
`timeStamp` varchar(200) NOT NULL,
|
|
`email_id` varchar(80) NOT NULL,
|
|
PRIMARY KEY (`id`),
|
|
KEY `emailPremium_emaillogs_email_id_9ef49552_fk_e_users_email` (`email_id`),
|
|
CONSTRAINT `emailPremium_emaillogs_email_id_9ef49552_fk_e_users_email` FOREIGN KEY (`email_id`) REFERENCES `e_users` (`email`)
|
|
)"""
|
|
try:
|
|
cursor.execute(query)
|
|
except:
|
|
pass
|
|
|
|
# Email Filtering Tables - Catch-All, Plus-Addressing, Pattern Forwarding
|
|
query = """CREATE TABLE IF NOT EXISTS `e_catchall` (
|
|
`domain_id` varchar(50) NOT NULL,
|
|
`destination` varchar(255) NOT NULL,
|
|
`enabled` tinyint(1) NOT NULL DEFAULT 1,
|
|
PRIMARY KEY (`domain_id`),
|
|
CONSTRAINT `fk_catchall_domain` FOREIGN KEY (`domain_id`) REFERENCES `e_domains` (`domain`) ON DELETE CASCADE
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4"""
|
|
try:
|
|
cursor.execute(query)
|
|
except:
|
|
pass
|
|
|
|
try:
|
|
connection.close()
|
|
except:
|
|
pass
|
|
except:
|
|
pass
|
|
|
|
@staticmethod
|
|
def emailMarketingMigrationsa():
|
|
try:
|
|
connection, cursor = Upgrade.setupConnection('cyberpanel')
|
|
|
|
query = """CREATE TABLE `emailMarketing_emailmarketing` (
|
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
`userName` varchar(50) NOT NULL,
|
|
PRIMARY KEY (`id`),
|
|
UNIQUE KEY `userName` (`userName`)
|
|
)"""
|
|
try:
|
|
cursor.execute(query)
|
|
except:
|
|
pass
|
|
|
|
query = """CREATE TABLE `emailMarketing_emaillists` (
|
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
`listName` varchar(50) NOT NULL,
|
|
`dateCreated` varchar(200) NOT NULL,
|
|
`owner_id` int(11) NOT NULL,
|
|
PRIMARY KEY (`id`),
|
|
UNIQUE KEY `listName` (`listName`),
|
|
KEY `emailMarketing_email_owner_id_bf1b4530_fk_websiteFu` (`owner_id`),
|
|
CONSTRAINT `emailMarketing_email_owner_id_bf1b4530_fk_websiteFu` FOREIGN KEY (`owner_id`) REFERENCES `websiteFunctions_websites` (`id`)
|
|
)"""
|
|
try:
|
|
cursor.execute(query)
|
|
except:
|
|
pass
|
|
|
|
query = 'ALTER TABLE emailMarketing_emaillists ADD COLUMN verified INT DEFAULT 0'
|
|
|
|
try:
|
|
cursor.execute(query)
|
|
except:
|
|
pass
|
|
|
|
query = 'ALTER TABLE emailMarketing_emaillists ADD COLUMN notVerified INT DEFAULT 0'
|
|
|
|
try:
|
|
cursor.execute(query)
|
|
except:
|
|
pass
|
|
|
|
query = """CREATE TABLE `emailMarketing_emailsinlist` (
|
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
`email` varchar(50) NOT NULL,
|
|
`firstName` varchar(20) NOT NULL,
|
|
`lastName` varchar(20) NOT NULL,
|
|
`verificationStatus` varchar(100) NOT NULL,
|
|
`dateCreated` varchar(200) NOT NULL,
|
|
`owner_id` int(11) NOT NULL,
|
|
PRIMARY KEY (`id`),
|
|
KEY `emailMarketing_email_owner_id_c5c27005_fk_emailMark` (`owner_id`),
|
|
CONSTRAINT `emailMarketing_email_owner_id_c5c27005_fk_emailMark` FOREIGN KEY (`owner_id`) REFERENCES `emailMarketing_emaillists` (`id`)
|
|
)"""
|
|
|
|
try:
|
|
cursor.execute(query)
|
|
except:
|
|
pass
|
|
|
|
query = """CREATE TABLE `emailMarketing_smtphosts` (
|
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
`host` varchar(150) NOT NULL,
|
|
`port` varchar(10) NOT NULL,
|
|
`userName` varchar(50) NOT NULL,
|
|
`password` varchar(50) NOT NULL,
|
|
`owner_id` int(11) NOT NULL,
|
|
PRIMARY KEY (`id`),
|
|
UNIQUE KEY `host` (`host`),
|
|
KEY `emailMarketing_smtph_owner_id_8b2d4ac7_fk_loginSyst` (`owner_id`),
|
|
CONSTRAINT `emailMarketing_smtph_owner_id_8b2d4ac7_fk_loginSyst` FOREIGN KEY (`owner_id`) REFERENCES `loginSystem_administrator` (`id`)
|
|
)"""
|
|
|
|
try:
|
|
cursor.execute(query)
|
|
except:
|
|
pass
|
|
|
|
query = """CREATE TABLE `emailMarketing_emailtemplate` (
|
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
`name` varchar(100) NOT NULL,
|
|
`subject` varchar(1000) NOT NULL,
|
|
`fromName` varchar(100) NOT NULL,
|
|
`fromEmail` varchar(150) NOT NULL,
|
|
`replyTo` varchar(150) NOT NULL,
|
|
`emailMessage` varchar(30000) NOT NULL,
|
|
`owner_id` int(11) NOT NULL,
|
|
PRIMARY KEY (`id`),
|
|
UNIQUE KEY `name` (`name`),
|
|
KEY `emailMarketing_email_owner_id_d27e1d00_fk_loginSyst` (`owner_id`),
|
|
CONSTRAINT `emailMarketing_email_owner_id_d27e1d00_fk_loginSyst` FOREIGN KEY (`owner_id`) REFERENCES `loginSystem_administrator` (`id`)
|
|
)"""
|
|
|
|
try:
|
|
cursor.execute(query)
|
|
except:
|
|
pass
|
|
|
|
query = """CREATE TABLE `emailMarketing_emailjobs` (
|
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
`date` varchar(200) NOT NULL,
|
|
`host` varchar(1000) NOT NULL,
|
|
`totalEmails` int(11) NOT NULL,
|
|
`sent` int(11) NOT NULL,
|
|
`failed` int(11) NOT NULL,
|
|
`owner_id` int(11) NOT NULL,
|
|
PRIMARY KEY (`id`),
|
|
KEY `emailMarketing_email_owner_id_73ee4827_fk_emailMark` (`owner_id`),
|
|
CONSTRAINT `emailMarketing_email_owner_id_73ee4827_fk_emailMark` FOREIGN KEY (`owner_id`) REFERENCES `emailMarketing_emailtemplate` (`id`)
|
|
)"""
|
|
|
|
try:
|
|
cursor.execute(query)
|
|
except:
|
|
pass
|
|
|
|
query = """CREATE TABLE `mailServer_pipeprograms` (
|
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
`source` varchar(80) NOT NULL,
|
|
`destination` longtext NOT NULL,
|
|
PRIMARY KEY (`id`)
|
|
)"""
|
|
|
|
try:
|
|
cursor.execute(query)
|
|
except:
|
|
pass
|
|
|
|
query = """CREATE TABLE `emailMarketing_validationlog` (
|
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
`status` int(11) NOT NULL,
|
|
`message` longtext NOT NULL,
|
|
`owner_id` int(11) NOT NULL,
|
|
PRIMARY KEY (`id`),
|
|
KEY `emailMarketing_valid_owner_id_240ad36e_fk_emailMark` (`owner_id`),
|
|
CONSTRAINT `emailMarketing_valid_owner_id_240ad36e_fk_emailMark` FOREIGN KEY (`owner_id`) REFERENCES `emailMarketing_emaillists` (`id`)
|
|
)"""
|
|
|
|
try:
|
|
cursor.execute(query)
|
|
except:
|
|
pass
|
|
|
|
try:
|
|
connection.close()
|
|
except:
|
|
pass
|
|
except:
|
|
pass
|
|
|
|
@staticmethod
|
|
def dockerMigrations():
|
|
try:
|
|
connection, cursor = Upgrade.setupConnection('cyberpanel')
|
|
|
|
query = """CREATE TABLE `dockerManager_containers` (
|
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
`name` varchar(50) NOT NULL,
|
|
`cid` varchar(64) NOT NULL,
|
|
`image` varchar(50) NOT NULL,
|
|
`tag` varchar(50) NOT NULL,
|
|
`memory` int(11) NOT NULL,
|
|
`ports` longtext NOT NULL,
|
|
`env` longtext NOT NULL,
|
|
`startOnReboot` int(11) NOT NULL,
|
|
`admin_id` int(11) NOT NULL,
|
|
PRIMARY KEY (`id`),
|
|
UNIQUE KEY `name` (`name`),
|
|
KEY `dockerManager_contai_admin_id_58fb62b7_fk_loginSyst` (`admin_id`),
|
|
CONSTRAINT `dockerManager_contai_admin_id_58fb62b7_fk_loginSyst` FOREIGN KEY (`admin_id`) REFERENCES `loginSystem_administrator` (`id`)
|
|
)"""
|
|
try:
|
|
cursor.execute(query)
|
|
except:
|
|
pass
|
|
|
|
try:
|
|
cursor.execute('ALTER TABLE loginSystem_administrator ADD config longtext')
|
|
except:
|
|
pass
|
|
|
|
try:
|
|
cursor.execute('ALTER TABLE loginSystem_acl ADD config longtext')
|
|
except:
|
|
pass
|
|
|
|
try:
|
|
cursor.execute('ALTER TABLE dockerManager_containers ADD volumes longtext')
|
|
except:
|
|
pass
|
|
|
|
try:
|
|
cursor.execute('ALTER TABLE dockerManager_containers MODIFY COLUMN name VARCHAR(150);')
|
|
except:
|
|
pass
|
|
|
|
# Add new fields for network configuration and extra options
|
|
try:
|
|
cursor.execute('ALTER TABLE dockerManager_containers ADD network VARCHAR(100) DEFAULT "bridge"')
|
|
except:
|
|
pass
|
|
|
|
try:
|
|
cursor.execute('ALTER TABLE dockerManager_containers ADD network_mode VARCHAR(50) DEFAULT "bridge"')
|
|
except:
|
|
pass
|
|
|
|
try:
|
|
cursor.execute('ALTER TABLE dockerManager_containers ADD extra_options LONGTEXT DEFAULT "{}"')
|
|
except:
|
|
pass
|
|
|
|
try:
|
|
connection.close()
|
|
except:
|
|
pass
|
|
except:
|
|
pass
|
|
|
|
@staticmethod
|
|
def containerMigrations():
|
|
try:
|
|
connection, cursor = Upgrade.setupConnection('cyberpanel')
|
|
|
|
query = """CREATE TABLE `containerization_containerlimits` (
|
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
`cpuPers` varchar(10) NOT NULL,
|
|
`IO` varchar(10) NOT NULL,
|
|
`IOPS` varchar(10) NOT NULL,
|
|
`memory` varchar(10) NOT NULL,
|
|
`networkSpeed` varchar(10) NOT NULL,
|
|
`networkHexValue` varchar(10) NOT NULL,
|
|
`enforce` int(11) NOT NULL,
|
|
`owner_id` int(11) NOT NULL,
|
|
PRIMARY KEY (`id`),
|
|
KEY `containerization_con_owner_id_494eb637_fk_websiteFu` (`owner_id`),
|
|
CONSTRAINT `containerization_con_owner_id_494eb637_fk_websiteFu` FOREIGN KEY (`owner_id`) REFERENCES `websiteFunctions_websites` (`id`)
|
|
)"""
|
|
try:
|
|
cursor.execute(query)
|
|
except:
|
|
pass
|
|
|
|
query = """CREATE TABLE `websiteFunctions_dockerpackages` (`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY, `Name` varchar(100) NOT NULL, `CPUs` integer NOT NULL, `Ram` integer NOT NULL, `Bandwidth` longtext NOT NULL, `DiskSpace` longtext NOT NULL, `config` longtext NOT NULL);"""
|
|
try:
|
|
cursor.execute(query)
|
|
except:
|
|
pass
|
|
|
|
query = """CREATE TABLE `websiteFunctions_dockersites` (`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY, `ComposePath` longtext NOT NULL, `SitePath` longtext NOT NULL, `MySQLPath` longtext NOT NULL, `state` integer NOT NULL, `SiteType` integer NOT NULL, `MySQLDBName` varchar(100) NOT NULL, `MySQLDBNUser` varchar(100) NOT NULL, `CPUsMySQL` varchar(100) NOT NULL, `MemoryMySQL` varchar(100) NOT NULL, `port` varchar(100) NOT NULL, `CPUsSite` varchar(100) NOT NULL, `MemorySite` varchar(100) NOT NULL, `SiteName` varchar(255) NOT NULL UNIQUE, `finalURL` longtext NOT NULL, `blogTitle` longtext NOT NULL, `adminUser` varchar(100) NOT NULL, `adminEmail` varchar(100) NOT NULL, `admin_id` integer NOT NULL);"""
|
|
try:
|
|
cursor.execute(query)
|
|
except:
|
|
pass
|
|
|
|
query = "ALTER TABLE `websiteFunctions_dockersites` ADD CONSTRAINT `websiteFunctions_doc_admin_id_88f5cb6d_fk_websiteFu` FOREIGN KEY (`admin_id`) REFERENCES `websiteFunctions_websites` (`id`);"
|
|
try:
|
|
cursor.execute(query)
|
|
except:
|
|
pass
|
|
|
|
query = "CREATE TABLE `websiteFunctions_packageassignment` (`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY, `package_id` integer NOT NULL, `user_id` integer NOT NULL);"
|
|
try:
|
|
cursor.execute(query)
|
|
except:
|
|
pass
|
|
|
|
|
|
query = """ALTER TABLE `websiteFunctions_packageassignment` ADD CONSTRAINT `websiteFunctions_pac_package_id_420b6aff_fk_websiteFu` FOREIGN KEY (`package_id`) REFERENCES `websiteFunctions_dockerpackages` (`id`);"""
|
|
try:
|
|
cursor.execute(query)
|
|
except:
|
|
pass
|
|
|
|
query = "ALTER TABLE `websiteFunctions_packageassignment` ADD CONSTRAINT `websiteFunctions_pac_user_id_864958ce_fk_loginSyst` FOREIGN KEY (`user_id`) REFERENCES `loginSystem_administrator` (`id`);"
|
|
try:
|
|
cursor.execute(query)
|
|
except:
|
|
pass
|
|
|
|
query = """ALTER TABLE `websiteFunctions_dockersites` ADD CONSTRAINT `websiteFunctions_doc_admin_id_88f5cb6d_fk_websiteFu` FOREIGN KEY (`admin_id`) REFERENCES `websiteFunctions_websites` (`id`);"""
|
|
try:
|
|
cursor.execute(query)
|
|
except:
|
|
pass
|
|
|
|
try:
|
|
connection.close()
|
|
except:
|
|
pass
|
|
except:
|
|
pass
|
|
|
|
@staticmethod
|
|
def CLMigrations():
|
|
try:
|
|
connection, cursor = Upgrade.setupConnection('cyberpanel')
|
|
|
|
query = """CREATE TABLE `CLManager_clpackages` (
|
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
`name` varchar(50) NOT NULL,
|
|
`speed` varchar(50) NOT NULL,
|
|
`vmem` varchar(50) NOT NULL,
|
|
`pmem` varchar(50) NOT NULL,
|
|
`io` varchar(50) NOT NULL,
|
|
`iops` varchar(50) NOT NULL,
|
|
`ep` varchar(50) NOT NULL,
|
|
`nproc` varchar(50) NOT NULL,
|
|
`inodessoft` varchar(50) NOT NULL,
|
|
`inodeshard` varchar(50) NOT NULL,
|
|
`owner_id` int(11) NOT NULL,
|
|
PRIMARY KEY (`id`),
|
|
UNIQUE KEY `name` (`name`),
|
|
KEY `CLManager_clpackages_owner_id_9898c1e8_fk_packages_package_id` (`owner_id`),
|
|
CONSTRAINT `CLManager_clpackages_owner_id_9898c1e8_fk_packages_package_id` FOREIGN KEY (`owner_id`) REFERENCES `packages_package` (`id`)
|
|
)"""
|
|
try:
|
|
cursor.execute(query)
|
|
except:
|
|
pass
|
|
|
|
query = "ALTER TABLE packages_package ADD COLUMN allowFullDomain INT DEFAULT 1;"
|
|
try:
|
|
cursor.execute(query)
|
|
except:
|
|
pass
|
|
|
|
query = "ALTER TABLE packages_package ADD COLUMN enforceDiskLimits INT DEFAULT 0;"
|
|
try:
|
|
cursor.execute(query)
|
|
except:
|
|
pass
|
|
|
|
try:
|
|
connection.close()
|
|
except:
|
|
pass
|
|
except:
|
|
pass
|
|
|
|
@staticmethod
|
|
def manageServiceMigrations():
|
|
try:
|
|
connection, cursor = Upgrade.setupConnection('cyberpanel')
|
|
|
|
query = """CREATE TABLE `manageServices_pdnsstatus` (
|
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
`serverStatus` int(11) NOT NULL,
|
|
`type` varchar(6) NOT NULL,
|
|
PRIMARY KEY (`id`)
|
|
)"""
|
|
try:
|
|
cursor.execute(query)
|
|
except:
|
|
pass
|
|
|
|
try:
|
|
cursor.execute('alter table manageServices_pdnsstatus add masterServer varchar(200)')
|
|
except:
|
|
pass
|
|
|
|
try:
|
|
cursor.execute('alter table manageServices_pdnsstatus add masterIP varchar(200)')
|
|
except:
|
|
pass
|
|
|
|
try:
|
|
cursor.execute('ALTER TABLE `manageServices_pdnsstatus` CHANGE `type` `type` VARCHAR(10) NULL;')
|
|
except:
|
|
pass
|
|
|
|
query = '''CREATE TABLE `databases_dbmeta` (
|
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
`key` varchar(200) NOT NULL,
|
|
`value` longtext NOT NULL,
|
|
`database_id` int(11) NOT NULL,
|
|
PRIMARY KEY (`id`),
|
|
KEY `databases_dbmeta_database_id_777997bc_fk_databases_databases_id` (`database_id`),
|
|
CONSTRAINT `databases_dbmeta_database_id_777997bc_fk_databases_databases_id` FOREIGN KEY (`database_id`) REFERENCES `databases_databases` (`id`)
|
|
)'''
|
|
|
|
try:
|
|
cursor.execute(query)
|
|
except:
|
|
pass
|
|
|
|
query = """CREATE TABLE `filemanager_trash` (
|
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
`originalPath` varchar(500) NOT NULL,
|
|
`fileName` varchar(200) NOT NULL,
|
|
`website_id` int(11) NOT NULL,
|
|
PRIMARY KEY (`id`),
|
|
KEY `filemanager_trash_website_id_e2762f3c_fk_websiteFu` (`website_id`),
|
|
CONSTRAINT `filemanager_trash_website_id_e2762f3c_fk_websiteFu` FOREIGN KEY (`website_id`) REFERENCES `websiteFunctions_websites` (`id`)
|
|
)"""
|
|
|
|
try:
|
|
cursor.execute(query)
|
|
except:
|
|
pass
|
|
|
|
query = """CREATE TABLE `databases_globaluserdb` (
|
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
`username` varchar(200) NOT NULL,
|
|
`password` varchar(500) NOT NULL,
|
|
`token` varchar(20) NOT NULL,
|
|
PRIMARY KEY (`id`)
|
|
)"""
|
|
|
|
try:
|
|
cursor.execute(query)
|
|
except:
|
|
pass
|
|
|
|
query = "CREATE TABLE `databases_databasesusers` (`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY, `username` varchar(50) NOT NULL UNIQUE, `owner_id` integer NOT NULL)"
|
|
|
|
try:
|
|
cursor.execute(query)
|
|
except:
|
|
pass
|
|
|
|
query = "ALTER TABLE `databases_databasesusers` ADD CONSTRAINT `databases_databasesu_owner_id_908fc638_fk_databases` FOREIGN KEY (`owner_id`) REFERENCES `databases_databases` (`id`);"
|
|
|
|
try:
|
|
cursor.execute(query)
|
|
except:
|
|
pass
|
|
|
|
try:
|
|
connection.close()
|
|
except:
|
|
pass
|
|
except:
|
|
pass
|
|
|
|
@staticmethod
|
|
def GeneralMigrations():
|
|
try:
|
|
|
|
cwd = os.getcwd()
|
|
os.chdir('/usr/local/CyberCP')
|
|
|
|
command = '/usr/local/CyberPanel/bin/python manage.py makemigrations'
|
|
Upgrade.executioner(command, 'python manage.py makemigrations', 0)
|
|
|
|
command = '/usr/local/CyberPanel/bin/python manage.py makemigrations'
|
|
Upgrade.executioner(command, '/usr/local/CyberPanel/bin/python manage.py migrate', 0)
|
|
|
|
os.chdir(cwd)
|
|
|
|
except:
|
|
pass
|
|
|
|
@staticmethod
|
|
def fixBaseTemplateMigrations():
|
|
"""
|
|
Fix baseTemplate migrations to prevent NodeNotFoundError on AlmaLinux 9 and Ubuntu 24
|
|
"""
|
|
try:
|
|
Upgrade.stdOut("Fixing baseTemplate migrations for AlmaLinux 9 and Ubuntu 24 compatibility...")
|
|
|
|
# Ensure baseTemplate migrations directory exists
|
|
migrations_dir = "/usr/local/CyberCP/baseTemplate/migrations"
|
|
if not os.path.exists(migrations_dir):
|
|
os.makedirs(migrations_dir)
|
|
Upgrade.stdOut("Created baseTemplate migrations directory")
|
|
|
|
# Create __init__.py if it doesn't exist
|
|
init_file = os.path.join(migrations_dir, "__init__.py")
|
|
if not os.path.exists(init_file):
|
|
with open(init_file, 'w') as f:
|
|
f.write("")
|
|
Upgrade.stdOut("Created baseTemplate migrations __init__.py")
|
|
|
|
# Create 0001_initial.py if it doesn't exist
|
|
initial_migration = os.path.join(migrations_dir, "0001_initial.py")
|
|
if not os.path.exists(initial_migration):
|
|
initial_content = '''# Generated by Django 3.2.25 on 2024-01-01 00:00
|
|
|
|
from django.db import migrations, models
|
|
|
|
|
|
class Migration(migrations.Migration):
|
|
|
|
initial = True
|
|
|
|
dependencies = [
|
|
]
|
|
|
|
operations = [
|
|
migrations.CreateModel(
|
|
name='CyberPanelCosmetic',
|
|
fields=[
|
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
('MainDashboardCSS', models.TextField(default='')),
|
|
],
|
|
),
|
|
migrations.CreateModel(
|
|
name='UserNotificationPreferences',
|
|
fields=[
|
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
('backup_notification_dismissed', models.BooleanField(default=False, help_text='Whether user has dismissed the backup notification')),
|
|
('ai_scanner_notification_dismissed', models.BooleanField(default=False, help_text='Whether user has dismissed the AI scanner notification')),
|
|
('created_at', models.DateTimeField(auto_now_add=True)),
|
|
('updated_at', models.DateTimeField(auto_now=True)),
|
|
],
|
|
options={
|
|
'verbose_name': 'User Notification Preferences',
|
|
'verbose_name_plural': 'User Notification Preferences',
|
|
},
|
|
),
|
|
migrations.CreateModel(
|
|
name='version',
|
|
fields=[
|
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
('version', models.CharField(max_length=10)),
|
|
('build', models.IntegerField()),
|
|
],
|
|
),
|
|
]
|
|
'''
|
|
with open(initial_migration, 'w') as f:
|
|
f.write(initial_content)
|
|
Upgrade.stdOut("Created baseTemplate 0001_initial.py migration")
|
|
|
|
# Create 0002_usernotificationpreferences.py if it doesn't exist
|
|
notification_migration = os.path.join(migrations_dir, "0002_usernotificationpreferences.py")
|
|
if not os.path.exists(notification_migration):
|
|
notification_content = '''# Generated by Django 3.2.25 on 2024-01-01 00:01
|
|
|
|
from django.db import migrations, models
|
|
import django.db.models.deletion
|
|
|
|
|
|
class Migration(migrations.Migration):
|
|
|
|
dependencies = [
|
|
('baseTemplate', '0001_initial'),
|
|
('loginSystem', '0001_initial'),
|
|
]
|
|
|
|
operations = [
|
|
migrations.AddField(
|
|
model_name='usernotificationpreferences',
|
|
name='user',
|
|
field=models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='notification_preferences', to='loginSystem.administrator'),
|
|
),
|
|
]
|
|
'''
|
|
with open(notification_migration, 'w') as f:
|
|
f.write(notification_content)
|
|
Upgrade.stdOut("Created baseTemplate 0002_usernotificationpreferences.py migration")
|
|
|
|
# Set proper permissions
|
|
command = "chown -R root:root " + migrations_dir
|
|
Upgrade.executioner(command, 0)
|
|
|
|
command = "chmod -R 755 " + migrations_dir
|
|
Upgrade.executioner(command, 0)
|
|
|
|
# Update Django settings to include DEFAULT_AUTO_FIELD if not present
|
|
settings_file = "/usr/local/CyberCP/CyberCP/settings.py"
|
|
if os.path.exists(settings_file):
|
|
with open(settings_file, 'r') as f:
|
|
settings_content = f.read()
|
|
|
|
if "DEFAULT_AUTO_FIELD" not in settings_content:
|
|
with open(settings_file, 'a') as f:
|
|
f.write("\n# Default primary key field type\n")
|
|
f.write("# https://docs.djangoproject.com/en/3.2/ref/settings/#default-auto-field\n")
|
|
f.write("DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'\n")
|
|
Upgrade.stdOut("Added DEFAULT_AUTO_FIELD to Django settings")
|
|
|
|
Upgrade.stdOut("baseTemplate migrations fixed successfully")
|
|
|
|
except Exception as e:
|
|
Upgrade.stdOut("Error fixing baseTemplate migrations: " + str(e))
|
|
|
|
@staticmethod
|
|
def IncBackupMigrations():
|
|
try:
|
|
connection, cursor = Upgrade.setupConnection('cyberpanel')
|
|
|
|
query = """CREATE TABLE `IncBackups_backupjob` (
|
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
`destination` varchar(300) NOT NULL,
|
|
`frequency` varchar(50) NOT NULL,
|
|
`websiteData` int(11) NOT NULL,
|
|
`websiteDatabases` int(11) NOT NULL,
|
|
`websiteDataEmails` int(11) NOT NULL,
|
|
PRIMARY KEY (`id`)
|
|
)"""
|
|
try:
|
|
cursor.execute(query)
|
|
except:
|
|
pass
|
|
|
|
query = 'ALTER TABLE IncBackups_backupjob ADD retention integer DEFAULT 0'
|
|
|
|
try:
|
|
cursor.execute(query)
|
|
except:
|
|
pass
|
|
|
|
query = """CREATE TABLE `IncBackups_incjob` (
|
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
`date` datetime(6) NOT NULL,
|
|
`website_id` int(11) NOT NULL,
|
|
PRIMARY KEY (`id`),
|
|
KEY `IncBackups_incjob_website_id_aad31bf6_fk_websiteFu` (`website_id`),
|
|
CONSTRAINT `IncBackups_incjob_website_id_aad31bf6_fk_websiteFu` FOREIGN KEY (`website_id`) REFERENCES `websiteFunctions_websites` (`id`)
|
|
)"""
|
|
try:
|
|
cursor.execute(query)
|
|
except:
|
|
pass
|
|
|
|
query = """CREATE TABLE `IncBackups_jobsites` (
|
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
`website` varchar(300) NOT NULL,
|
|
`job_id` int(11) NOT NULL,
|
|
PRIMARY KEY (`id`),
|
|
KEY `IncBackups_jobsites_job_id_494a1f69_fk_IncBackups_backupjob_id` (`job_id`),
|
|
CONSTRAINT `IncBackups_jobsites_job_id_494a1f69_fk_IncBackups_backupjob_id` FOREIGN KEY (`job_id`) REFERENCES `IncBackups_backupjob` (`id`)
|
|
)"""
|
|
try:
|
|
cursor.execute(query)
|
|
except:
|
|
pass
|
|
|
|
query = """CREATE TABLE `IncBackups_jobsnapshots` (
|
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
`type` varchar(300) NOT NULL,
|
|
`snapshotid` varchar(50) NOT NULL,
|
|
`job_id` int(11) NOT NULL,
|
|
`destination` varchar(200) NOT NULL,
|
|
PRIMARY KEY (`id`),
|
|
KEY `IncBackups_jobsnapshots_job_id_a8237ca8_fk_IncBackups_incjob_id` (`job_id`),
|
|
CONSTRAINT `IncBackups_jobsnapshots_job_id_a8237ca8_fk_IncBackups_incjob_id` FOREIGN KEY (`job_id`) REFERENCES `IncBackups_incjob` (`id`)
|
|
)"""
|
|
try:
|
|
cursor.execute(query)
|
|
except:
|
|
pass
|
|
|
|
query = """CREATE TABLE `websiteFunctions_gitlogs` (
|
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
`date` datetime(6) NOT NULL,
|
|
`type` varchar(5) NOT NULL,
|
|
`message` longtext NOT NULL,
|
|
`owner_id` int(11) NOT NULL,
|
|
PRIMARY KEY (`id`),
|
|
KEY `websiteFunctions_git_owner_id_ce74c7de_fk_websiteFu` (`owner_id`),
|
|
CONSTRAINT `websiteFunctions_git_owner_id_ce74c7de_fk_websiteFu` FOREIGN KEY (`owner_id`) REFERENCES `websiteFunctions_websites` (`id`)
|
|
)"""
|
|
|
|
try:
|
|
cursor.execute(query)
|
|
except:
|
|
pass
|
|
|
|
query = """CREATE TABLE `websiteFunctions_backupjob` (
|
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
`logFile` varchar(1000) NOT NULL,
|
|
`ipAddress` varchar(50) NOT NULL,
|
|
`port` varchar(15) NOT NULL,
|
|
`jobFailedSites` int(11) NOT NULL,
|
|
`jobSuccessSites` int(11) NOT NULL,
|
|
`location` int(11) NOT NULL,
|
|
PRIMARY KEY (`id`)
|
|
)"""
|
|
try:
|
|
cursor.execute(query)
|
|
except:
|
|
pass
|
|
|
|
query = """CREATE TABLE `websiteFunctions_backupjoblogs` (
|
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
`message` longtext NOT NULL,
|
|
`owner_id` int(11) NOT NULL,
|
|
`status` int(11) NOT NULL,
|
|
PRIMARY KEY (`id`),
|
|
KEY `websiteFunctions_bac_owner_id_af3d15f9_fk_websiteFu` (`owner_id`),
|
|
CONSTRAINT `websiteFunctions_bac_owner_id_af3d15f9_fk_websiteFu` FOREIGN KEY (`owner_id`) REFERENCES `websiteFunctions_backupjob` (`id`)
|
|
)"""
|
|
|
|
try:
|
|
cursor.execute(query)
|
|
except:
|
|
pass
|
|
|
|
query = """CREATE TABLE `websiteFunctions_gdrive` (
|
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
`name` varchar(50) NOT NULL,
|
|
`auth` longtext NOT NULL,
|
|
`runTime` varchar(20) NOT NULL,
|
|
`owner_id` int(11) NOT NULL,
|
|
PRIMARY KEY (`id`),
|
|
UNIQUE KEY `name` (`name`),
|
|
KEY `websiteFunctions_gdr_owner_id_b5b1e86f_fk_loginSyst` (`owner_id`),
|
|
CONSTRAINT `websiteFunctions_gdr_owner_id_b5b1e86f_fk_loginSyst` FOREIGN KEY (`owner_id`) REFERENCES `loginSystem_administrator` (`id`)
|
|
)"""
|
|
|
|
try:
|
|
cursor.execute(query)
|
|
except:
|
|
pass
|
|
|
|
query = """CREATE TABLE `websiteFunctions_gdrivesites` (
|
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
`domain` varchar(200) NOT NULL,
|
|
`owner_id` int(11) NOT NULL,
|
|
PRIMARY KEY (`id`),
|
|
KEY `websiteFunctions_gdr_owner_id_ff78b305_fk_websiteFu` (`owner_id`),
|
|
CONSTRAINT `websiteFunctions_gdr_owner_id_ff78b305_fk_websiteFu` FOREIGN KEY (`owner_id`) REFERENCES `websiteFunctions_gdrive` (`id`)
|
|
)"""
|
|
|
|
try:
|
|
cursor.execute(query)
|
|
except:
|
|
pass
|
|
|
|
query = """CREATE TABLE `websiteFunctions_gdrivejoblogs` (
|
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
`status` int(11) NOT NULL,
|
|
`message` longtext NOT NULL,
|
|
`owner_id` int(11) NOT NULL,
|
|
PRIMARY KEY (`id`),
|
|
KEY `websiteFunctions_gdr_owner_id_4cf7983e_fk_websiteFu` (`owner_id`),
|
|
CONSTRAINT `websiteFunctions_gdr_owner_id_4cf7983e_fk_websiteFu` FOREIGN KEY (`owner_id`) REFERENCES `websiteFunctions_gdrive` (`id`)
|
|
)"""
|
|
|
|
try:
|
|
cursor.execute(query)
|
|
except:
|
|
pass
|
|
|
|
query = "ALTER TABLE `websiteFunctions_childdomains` ADD `alais` INT NOT NULL DEFAULT '0' AFTER `master_id`; "
|
|
try:
|
|
cursor.execute(query)
|
|
except:
|
|
pass
|
|
|
|
|
|
try:
|
|
connection.close()
|
|
except:
|
|
pass
|
|
except:
|
|
pass
|
|
|
|
@staticmethod
|
|
def fixSubdomainLogConfigurations():
|
|
"""Fix subdomain log configurations during upgrade"""
|
|
try:
|
|
# Check if this fix has already been applied
|
|
fix_marker_file = '/usr/local/lscp/logs/subdomain_log_fix_applied'
|
|
if os.path.exists(fix_marker_file):
|
|
Upgrade.stdOut("Subdomain log fix already applied - skipping")
|
|
return
|
|
|
|
Upgrade.stdOut("=== FIXING SUBDOMAIN LOG CONFIGURATIONS ===")
|
|
|
|
# Import required modules
|
|
import sys
|
|
import os
|
|
sys.path.append('/usr/local/CyberCP')
|
|
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "CyberCP.settings")
|
|
|
|
try:
|
|
import django
|
|
django.setup()
|
|
|
|
from websiteFunctions.models import ChildDomains
|
|
from plogical.CyberCPLogFileWriter import CyberCPLogFileWriter as logging
|
|
from plogical.processUtilities import ProcessUtilities
|
|
import re
|
|
import shutil
|
|
from datetime import datetime
|
|
|
|
# Get all child domains
|
|
child_domains = ChildDomains.objects.all()
|
|
|
|
if not child_domains:
|
|
Upgrade.stdOut("No child domains found - skipping subdomain log fix")
|
|
return
|
|
|
|
Upgrade.stdOut(f"Found {len(child_domains)} child domains to check")
|
|
|
|
fixed_count = 0
|
|
skipped_count = 0
|
|
|
|
for child_domain in child_domains:
|
|
domain_name = child_domain.domain
|
|
master_domain = child_domain.master.domain
|
|
|
|
vhost_conf_path = f"/usr/local/lsws/conf/vhosts/{domain_name}/vhost.conf"
|
|
|
|
if not os.path.exists(vhost_conf_path):
|
|
Upgrade.stdOut(f"⚠️ Skipping {domain_name}: vHost config not found")
|
|
skipped_count += 1
|
|
continue
|
|
|
|
try:
|
|
# Read current configuration
|
|
with open(vhost_conf_path, 'r') as f:
|
|
config_content = f.read()
|
|
|
|
# Check if fix is needed
|
|
if f'{master_domain}.error_log' not in config_content and f'{master_domain}.access_log' not in config_content:
|
|
Upgrade.stdOut(f"✅ {domain_name}: Already has correct log configuration")
|
|
skipped_count += 1
|
|
continue
|
|
|
|
# Create backup
|
|
backup_path = f"{vhost_conf_path}.backup.{datetime.now().strftime('%Y%m%d_%H%M%S')}"
|
|
shutil.copy2(vhost_conf_path, backup_path)
|
|
|
|
# Fix the configuration
|
|
fixed_content = config_content
|
|
|
|
# Fix error log path
|
|
fixed_content = re.sub(
|
|
rf'errorlog\s+\$VH_ROOT/logs/{re.escape(master_domain)}\.error_log',
|
|
f'errorlog $VH_ROOT/logs/{domain_name}.error_log',
|
|
fixed_content
|
|
)
|
|
|
|
# Fix access log path
|
|
fixed_content = re.sub(
|
|
rf'accesslog\s+\$VH_ROOT/logs/{re.escape(master_domain)}\.access_log',
|
|
f'accesslog $VH_ROOT/logs/{domain_name}.access_log',
|
|
fixed_content
|
|
)
|
|
|
|
# Fix CustomLog paths (for Apache configurations)
|
|
fixed_content = re.sub(
|
|
rf'CustomLog\s+/home/{re.escape(master_domain)}/logs/{re.escape(master_domain)}\.access_log',
|
|
f'CustomLog /home/{domain_name}/logs/{domain_name}.access_log',
|
|
fixed_content
|
|
)
|
|
|
|
# Write the fixed configuration
|
|
with open(vhost_conf_path, 'w') as f:
|
|
f.write(fixed_content)
|
|
|
|
# Set proper ownership
|
|
ProcessUtilities.executioner(f'chown lsadm:lsadm {vhost_conf_path}')
|
|
|
|
# Create the log directory if it doesn't exist
|
|
log_dir = f"/home/{master_domain}/logs"
|
|
if not os.path.exists(log_dir):
|
|
os.makedirs(log_dir, exist_ok=True)
|
|
ProcessUtilities.executioner(f'chown -R {child_domain.master.externalApp}:{child_domain.master.externalApp} {log_dir}')
|
|
|
|
# Create separate log files for the child domain
|
|
error_log_path = f"{log_dir}/{domain_name}.error_log"
|
|
access_log_path = f"{log_dir}/{domain_name}.access_log"
|
|
|
|
# Create empty log files if they don't exist
|
|
for log_path in [error_log_path, access_log_path]:
|
|
if not os.path.exists(log_path):
|
|
with open(log_path, 'w') as f:
|
|
f.write('')
|
|
ProcessUtilities.executioner(f'chown {child_domain.master.externalApp}:{child_domain.master.externalApp} {log_path}')
|
|
ProcessUtilities.executioner(f'chmod 644 {log_path}')
|
|
|
|
Upgrade.stdOut(f"✅ Fixed log configuration for {domain_name}")
|
|
logging.writeToFile(f'Fixed subdomain log configuration for {domain_name} during upgrade')
|
|
fixed_count += 1
|
|
|
|
except Exception as e:
|
|
Upgrade.stdOut(f"❌ Failed to fix {domain_name}: {str(e)}")
|
|
logging.writeToFile(f'Error fixing subdomain logs for {domain_name} during upgrade: {str(e)}')
|
|
|
|
# Restart LiteSpeed to apply changes if any were made
|
|
if fixed_count > 0:
|
|
Upgrade.stdOut("Restarting LiteSpeed to apply log configuration changes...")
|
|
ProcessUtilities.executioner('systemctl restart lsws')
|
|
|
|
Upgrade.stdOut(f"=== SUBDOMAIN LOG FIX COMPLETE ===")
|
|
Upgrade.stdOut(f"Fixed: {fixed_count} domains")
|
|
Upgrade.stdOut(f"Skipped: {skipped_count} domains")
|
|
|
|
# Create marker file to indicate fix has been applied
|
|
try:
|
|
with open(fix_marker_file, 'w') as f:
|
|
f.write(f"Subdomain log fix applied on {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n")
|
|
f.write(f"Fixed domains: {fixed_count}\n")
|
|
f.write(f"Skipped domains: {skipped_count}\n")
|
|
except:
|
|
pass
|
|
|
|
except ImportError as e:
|
|
Upgrade.stdOut(f"⚠️ Django not available during upgrade: {str(e)}")
|
|
Upgrade.stdOut("Subdomain log fix will be applied on next CyberPanel restart")
|
|
|
|
except Exception as e:
|
|
Upgrade.stdOut(f"❌ Error in subdomain log fix: {str(e)}")
|
|
logging.writeToFile(f'Error in subdomain log fix during upgrade: {str(e)}')
|
|
|
|
@staticmethod
|
|
def enableServices():
|
|
try:
|
|
servicePath = '/home/cyberpanel/powerdns'
|
|
writeToFile = open(servicePath, 'w+')
|
|
writeToFile.close()
|
|
|
|
servicePath = '/home/cyberpanel/postfix'
|
|
writeToFile = open(servicePath, 'w+')
|
|
writeToFile.close()
|
|
|
|
servicePath = '/home/cyberpanel/pureftpd'
|
|
writeToFile = open(servicePath, 'w+')
|
|
writeToFile.close()
|
|
except:
|
|
pass
|
|
|
|
@staticmethod
|
|
def backupCriticalFiles():
|
|
"""Backup all critical configuration files before upgrade"""
|
|
import tempfile
|
|
backup_dir = tempfile.mkdtemp(prefix='cyberpanel_backup_')
|
|
|
|
critical_files = [
|
|
'/usr/local/CyberCP/CyberCP/settings.py',
|
|
'/usr/local/CyberCP/.git/config', # Git configuration
|
|
]
|
|
|
|
# Also backup any custom configurations
|
|
custom_configs = [
|
|
'/usr/local/CyberCP/baseTemplate/static/baseTemplate/custom/',
|
|
'/usr/local/CyberCP/public/phpmyadmin/config.inc.php',
|
|
'/usr/local/CyberCP/rainloop/data/_data_/',
|
|
]
|
|
|
|
# Backup Imunify360 directories and configuration
|
|
imunify_paths = [
|
|
'/usr/local/CyberCP/public/imunify',
|
|
'/usr/local/CyberCP/public/imunifyav',
|
|
'/etc/sysconfig/imunify360/integration.conf',
|
|
]
|
|
|
|
for imunify_path in imunify_paths:
|
|
if os.path.exists(imunify_path):
|
|
if os.path.isdir(imunify_path):
|
|
custom_configs.append(imunify_path)
|
|
else:
|
|
critical_files.append(imunify_path)
|
|
|
|
backed_up_files = {}
|
|
|
|
for file_path in critical_files:
|
|
if os.path.exists(file_path):
|
|
try:
|
|
backup_path = os.path.join(backup_dir, os.path.basename(file_path))
|
|
shutil.copy2(file_path, backup_path)
|
|
backed_up_files[file_path] = backup_path
|
|
Upgrade.stdOut(f"Backed up {file_path}")
|
|
except Exception as e:
|
|
Upgrade.stdOut(f"Failed to backup {file_path}: {str(e)}")
|
|
|
|
# Backup directories
|
|
for dir_path in custom_configs:
|
|
if os.path.exists(dir_path):
|
|
try:
|
|
backup_path = os.path.join(backup_dir, os.path.basename(dir_path))
|
|
shutil.copytree(dir_path, backup_path)
|
|
backed_up_files[dir_path] = backup_path
|
|
Upgrade.stdOut(f"Backed up directory {dir_path}")
|
|
except Exception as e:
|
|
Upgrade.stdOut(f"Failed to backup {dir_path}: {str(e)}")
|
|
|
|
return backup_dir, backed_up_files
|
|
|
|
@staticmethod
|
|
def restoreCriticalFiles(backup_dir, backed_up_files):
|
|
"""Restore critical configuration files after upgrade"""
|
|
for original_path, backup_path in backed_up_files.items():
|
|
# Skip settings.py - we'll handle it separately to preserve INSTALLED_APPS
|
|
if 'settings.py' in original_path:
|
|
Upgrade.stdOut(f"Skipping {original_path} - will be handled separately")
|
|
continue
|
|
|
|
try:
|
|
if os.path.isdir(backup_path):
|
|
if os.path.exists(original_path):
|
|
shutil.rmtree(original_path)
|
|
shutil.copytree(backup_path, original_path)
|
|
else:
|
|
# Create directory if it doesn't exist
|
|
os.makedirs(os.path.dirname(original_path), exist_ok=True)
|
|
shutil.copy2(backup_path, original_path)
|
|
Upgrade.stdOut(f"Restored {original_path}")
|
|
except Exception as e:
|
|
Upgrade.stdOut(f"Failed to restore {original_path}: {str(e)}")
|
|
|
|
@staticmethod
|
|
def downloadAndUpgrade(versionNumbring, branch):
|
|
try:
|
|
## Download latest version.
|
|
|
|
## Backup all critical files
|
|
Upgrade.stdOut("Backing up critical configuration files...")
|
|
backup_dir, backed_up_files = Upgrade.backupCriticalFiles()
|
|
|
|
## CyberPanel DB Creds
|
|
dbName = settings.DATABASES['default']['NAME']
|
|
dbUser = settings.DATABASES['default']['USER']
|
|
password = settings.DATABASES['default']['PASSWORD']
|
|
host = settings.DATABASES['default']['HOST']
|
|
port = settings.DATABASES['default']['PORT']
|
|
|
|
## Root DB Creds
|
|
|
|
rootdbName = settings.DATABASES['rootdb']['NAME']
|
|
rootdbdbUser = settings.DATABASES['rootdb']['USER']
|
|
rootdbpassword = settings.DATABASES['rootdb']['PASSWORD']
|
|
|
|
## Complete db string
|
|
|
|
completDBString = """\nDATABASES = {
|
|
'default': {
|
|
'ENGINE': 'django.db.backends.mysql',
|
|
'NAME': '%s',
|
|
'USER': '%s',
|
|
'PASSWORD': '%s',
|
|
'HOST': '%s',
|
|
'PORT':'%s'
|
|
},
|
|
'rootdb': {
|
|
'ENGINE': 'django.db.backends.mysql',
|
|
'NAME': '%s',
|
|
'USER': '%s',
|
|
'PASSWORD': '%s',
|
|
'HOST': '%s',
|
|
'PORT': '%s',
|
|
},
|
|
}\n""" % (dbName, dbUser, password, host, port, rootdbName, rootdbdbUser, rootdbpassword, host, port)
|
|
|
|
settingsFile = '/usr/local/CyberCP/CyberCP/settings.py'
|
|
|
|
Upgrade.stdOut("Critical files backed up to: " + backup_dir)
|
|
|
|
## Always do a fresh clone for clean upgrade
|
|
|
|
Upgrade.stdOut("Performing clean upgrade by removing and re-cloning CyberPanel...")
|
|
|
|
# Set git config first
|
|
command = 'git config --global user.email "support@cyberpanel.net"'
|
|
if not Upgrade.executioner(command, command, 1):
|
|
return 0, 'Failed to execute %s' % (command)
|
|
|
|
command = 'git config --global user.name "CyberPanel"'
|
|
if not Upgrade.executioner(command, command, 1):
|
|
return 0, 'Failed to execute %s' % (command)
|
|
|
|
# Change to parent directory
|
|
os.chdir('/usr/local')
|
|
|
|
# Remove old CyberCP directory
|
|
if os.path.exists('CyberCP'):
|
|
Upgrade.stdOut("Removing old CyberCP directory...")
|
|
try:
|
|
shutil.rmtree('CyberCP')
|
|
Upgrade.stdOut("Old CyberCP directory removed successfully.")
|
|
except Exception as e:
|
|
Upgrade.stdOut(f"Error removing CyberCP directory: {str(e)}")
|
|
# Try to restore backup if removal fails
|
|
Upgrade.restoreCriticalFiles(backup_dir, backed_up_files)
|
|
return 0, 'Failed to remove old CyberCP directory'
|
|
|
|
# Clone the new repository directly to CyberCP
|
|
Upgrade.stdOut("Cloning fresh CyberPanel repository...")
|
|
command = 'git clone https://github.com/usmannasir/cyberpanel CyberCP'
|
|
if not Upgrade.executioner(command, command, 1):
|
|
# Try to restore backup if clone fails
|
|
Upgrade.stdOut("Clone failed, attempting to restore backup...")
|
|
Upgrade.restoreCriticalFiles(backup_dir, backed_up_files)
|
|
return 0, 'Failed to clone CyberPanel repository'
|
|
|
|
# Checkout the correct branch
|
|
os.chdir('/usr/local/CyberCP')
|
|
command = 'git checkout %s' % (branch)
|
|
if not Upgrade.executioner(command, command, 1):
|
|
Upgrade.stdOut(f"Warning: Failed to checkout branch {branch}, continuing with default branch")
|
|
|
|
# Restore all backed up configuration files (except settings.py)
|
|
Upgrade.stdOut("Restoring configuration files...")
|
|
Upgrade.restoreCriticalFiles(backup_dir, backed_up_files)
|
|
|
|
## Handle settings.py separately to preserve NEW INSTALLED_APPS while keeping old database credentials
|
|
|
|
# Read the NEW settings file from the fresh clone (has new INSTALLED_APPS like 'aiScanner')
|
|
settingsData = open(settingsFile, 'r').read()
|
|
|
|
# Replace only the DATABASES section with our saved credentials
|
|
import re
|
|
|
|
# More precise pattern to match the entire DATABASES dictionary including nested dictionaries
|
|
# This pattern looks for DATABASES = { ... } including the 'default' and 'rootdb' nested dicts
|
|
database_pattern = r'DATABASES\s*=\s*\{[^}]*\{[^}]*\}[^}]*\{[^}]*\}[^}]*\}'
|
|
|
|
# Replace the DATABASES section with our saved credentials from before upgrade
|
|
settingsData = re.sub(database_pattern, completDBString.strip(), settingsData, flags=re.DOTALL)
|
|
|
|
# Write back the updated settings
|
|
writeToFile = open(settingsFile, 'w')
|
|
writeToFile.write(settingsData)
|
|
writeToFile.close()
|
|
|
|
Upgrade.stdOut('Settings file updated with database credentials while preserving new INSTALLED_APPS!')
|
|
|
|
Upgrade.staticContent()
|
|
|
|
# Restore Imunify360 after upgrade
|
|
Upgrade.restoreImunify360()
|
|
|
|
# FINAL STEP: Ensure Imunify360 execute permissions are set
|
|
Upgrade.finalImunifyPermissions()
|
|
|
|
return 1, None
|
|
|
|
except Exception as e:
|
|
ErrorSanitizer.log_error_securely(e, 'installLSCPD')
|
|
return 0, "Failed to install LSCPD"
|
|
|
|
@staticmethod
|
|
def installLSCPD(branch):
|
|
try:
|
|
|
|
if Upgrade.SoftUpgrade == 0:
|
|
|
|
Upgrade.stdOut("Starting LSCPD installation..")
|
|
|
|
cwd = os.getcwd()
|
|
|
|
os.chdir('/usr/local')
|
|
|
|
command = 'yum -y install gcc gcc-c++ make autoconf glibc rcs'
|
|
Upgrade.executioner(command, 'LSCPD Pre-reqs [one]', 0)
|
|
|
|
##
|
|
|
|
lscpdPath = '/usr/local/lscp/bin/lscpd'
|
|
|
|
if os.path.exists(lscpdPath):
|
|
os.remove(lscpdPath)
|
|
|
|
try:
|
|
try:
|
|
result = subprocess.run('uname -a', capture_output=True, universal_newlines=True, shell=True)
|
|
except:
|
|
result = subprocess.run('uname -a', stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, shell=True)
|
|
|
|
if result.stdout.find('aarch64') == -1:
|
|
lscpdSelection = 'lscpd-0.3.1'
|
|
if os.path.exists(Upgrade.UbuntuPath):
|
|
result = open(Upgrade.UbuntuPath, 'r').read()
|
|
if result.find('22.04') > -1 or result.find('24.04') > -1:
|
|
lscpdSelection = 'lscpd.0.4.0'
|
|
else:
|
|
lscpdSelection = 'lscpd.aarch64'
|
|
|
|
except:
|
|
|
|
lscpdSelection = 'lscpd-0.3.1'
|
|
if os.path.exists(Upgrade.UbuntuPath):
|
|
result = open(Upgrade.UbuntuPath, 'r').read()
|
|
if result.find('22.04') > -1 or result.find('24.04') > -1:
|
|
lscpdSelection = 'lscpd.0.4.0'
|
|
|
|
command = f'cp -f /usr/local/CyberCP/{lscpdSelection} /usr/local/lscp/bin/{lscpdSelection}'
|
|
Upgrade.executioner(command, command, 0)
|
|
|
|
command = 'rm -f /usr/local/lscp/bin/lscpd'
|
|
Upgrade.executioner(command, command, 0)
|
|
|
|
command = f'mv /usr/local/lscp/bin/{lscpdSelection} /usr/local/lscp/bin/lscpd'
|
|
Upgrade.executioner(command, command, 0)
|
|
|
|
command = f'chmod 755 {lscpdPath}'
|
|
Upgrade.executioner(command, 'LSCPD Download.', 0)
|
|
|
|
command = 'yum -y install pcre-devel openssl-devel expat-devel geoip-devel zlib-devel udns-devel which curl'
|
|
Upgrade.executioner(command, 'LSCPD Pre-reqs [two]', 0)
|
|
|
|
try:
|
|
pwd.getpwnam('lscpd')
|
|
except KeyError:
|
|
command = 'adduser lscpd -M -d /usr/local/lscp'
|
|
Upgrade.executioner(command, 'Add user LSCPD', 0)
|
|
|
|
try:
|
|
grp.getgrnam('lscpd')
|
|
except KeyError:
|
|
command = 'groupadd lscpd'
|
|
Upgrade.executioner(command, 'Add group LSCPD', 0)
|
|
|
|
command = 'usermod -a -G lscpd lscpd'
|
|
Upgrade.executioner(command, 'Add group LSCPD', 0)
|
|
|
|
command = 'usermod -a -G lsadm lscpd'
|
|
Upgrade.executioner(command, 'Add group LSCPD', 0)
|
|
|
|
command = 'systemctl daemon-reload'
|
|
Upgrade.executioner(command, 'daemon-reload LSCPD', 0)
|
|
|
|
command = 'systemctl restart lscpd'
|
|
Upgrade.executioner(command, 'Restart LSCPD', 0)
|
|
|
|
os.chdir(cwd)
|
|
|
|
Upgrade.stdOut("LSCPD successfully installed!")
|
|
|
|
except Exception as e:
|
|
ErrorSanitizer.log_error_securely(e, 'installLSCPD')
|
|
Upgrade.stdOut("Failed to install LSCPD [installLSCPD]")
|
|
|
|
### disable dkim signing in rspamd in ref to https://github.com/usmannasir/cyberpanel/issues/1176
|
|
@staticmethod
|
|
def FixRSPAMDConfig():
|
|
RSPAMDConf = '/etc/rspamd'
|
|
postfixConf = '/etc/postfix/main.cf'
|
|
|
|
if os.path.exists(RSPAMDConf):
|
|
DKIMPath = '/etc/rspamd/local.d/dkim_signing.conf'
|
|
|
|
WriteToFile = open(DKIMPath, 'w')
|
|
WriteToFile.write('enabled = false;\n')
|
|
WriteToFile.close()
|
|
|
|
if os.path.exists(postfixConf):
|
|
appendpath = "/etc/postfix/main.cf"
|
|
|
|
lines = open(appendpath, 'r').readlines()
|
|
|
|
WriteToFile = open(appendpath, 'w')
|
|
|
|
for line in lines:
|
|
|
|
if line.find('smtpd_milters') > -1:
|
|
continue
|
|
elif line.find('non_smtpd_milters') > -1:
|
|
continue
|
|
elif line.find('milter_default_action') > -1:
|
|
continue
|
|
else:
|
|
WriteToFile.write(line)
|
|
|
|
RSPAMDConfContent = '''
|
|
### Please do not edit this line, editing this line could break configurations
|
|
smtpd_milters = inet:127.0.0.1:8891, inet:127.0.0.1:11332
|
|
non_smtpd_milters = $smtpd_milters
|
|
milter_default_action = accept
|
|
'''
|
|
WriteToFile.write(RSPAMDConfContent)
|
|
|
|
WriteToFile.close()
|
|
|
|
command = 'systemctl restart postfix && systemctl restart rspamd'
|
|
Upgrade.executioner(command, 'postfix and rspamd restart', 0, True)
|
|
|
|
#### if you update this function needs to update this function on plogical.acl.py as well
|
|
@staticmethod
|
|
def fixPermissions():
|
|
try:
|
|
|
|
try:
|
|
def generate_pass(length=14):
|
|
chars = string.ascii_uppercase + string.ascii_lowercase + string.digits
|
|
size = length
|
|
return ''.join(random.choice(chars) for x in range(size))
|
|
|
|
content = """<?php
|
|
$_ENV['snappymail_INCLUDE_AS_API'] = true;
|
|
include '/usr/local/CyberCP/public/snappymail/index.php';
|
|
|
|
$oConfig = \snappymail\Api::Config();
|
|
$oConfig->SetPassword('%s');
|
|
echo $oConfig->Save() ? 'Done' : 'Error';
|
|
|
|
?>""" % (generate_pass())
|
|
|
|
writeToFile = open('/usr/local/CyberCP/public/snappymail.php', 'w')
|
|
writeToFile.write(content)
|
|
writeToFile.close()
|
|
|
|
command = "chown -R lscpd:lscpd /usr/local/lscp/cyberpanel/snappymail/data"
|
|
subprocess.call(shlex.split(command))
|
|
|
|
except:
|
|
pass
|
|
|
|
Upgrade.stdOut("Fixing permissions..")
|
|
|
|
command = "usermod -G lscpd,lsadm,nobody lscpd"
|
|
Upgrade.executioner(command, 'chown core code', 0)
|
|
|
|
command = "usermod -G lscpd,lsadm,nogroup lscpd"
|
|
Upgrade.executioner(command, 'chown core code', 0)
|
|
|
|
###### fix Core CyberPanel permissions
|
|
|
|
command = "find /usr/local/CyberCP -type d -exec chmod 0755 {} \;"
|
|
Upgrade.executioner(command, 'chown core code', 0)
|
|
|
|
command = "find /usr/local/CyberCP -type f -exec chmod 0644 {} \;"
|
|
Upgrade.executioner(command, 'chown core code', 0)
|
|
|
|
command = "chmod -R 755 /usr/local/CyberCP/bin"
|
|
Upgrade.executioner(command, 'chown core code', 0)
|
|
|
|
## change owner
|
|
|
|
command = "chown -R root:root /usr/local/CyberCP"
|
|
Upgrade.executioner(command, 'chown core code', 0)
|
|
|
|
########### Fix LSCPD
|
|
|
|
command = "find /usr/local/lscp -type d -exec chmod 0755 {} \;"
|
|
Upgrade.executioner(command, 'chown core code', 0)
|
|
|
|
command = "find /usr/local/lscp -type f -exec chmod 0644 {} \;"
|
|
Upgrade.executioner(command, 'chown core code', 0)
|
|
|
|
command = "chmod -R 755 /usr/local/lscp/bin"
|
|
Upgrade.executioner(command, 'chown core code', 0)
|
|
|
|
command = "chmod -R 755 /usr/local/lscp/fcgi-bin"
|
|
Upgrade.executioner(command, 'chown core code', 0)
|
|
|
|
command = "chown -R lscpd:lscpd /usr/local/CyberCP/public/phpmyadmin/tmp"
|
|
Upgrade.executioner(command, 'chown core code', 0)
|
|
|
|
## change owner
|
|
|
|
command = "chown -R root:root /usr/local/lscp"
|
|
Upgrade.executioner(command, 'chown core code', 0)
|
|
|
|
command = "chown -R lscpd:lscpd /usr/local/lscp/cyberpanel/rainloop"
|
|
Upgrade.executioner(command, 'chown core code', 0)
|
|
|
|
command = "chmod 700 /usr/local/CyberCP/cli/cyberPanel.py"
|
|
Upgrade.executioner(command, 'chown core code', 0)
|
|
|
|
command = "chmod 700 /usr/local/CyberCP/plogical/upgradeCritical.py"
|
|
Upgrade.executioner(command, 'chown core code', 0)
|
|
|
|
command = "chmod 755 /usr/local/CyberCP/postfixSenderPolicy/client.py"
|
|
Upgrade.executioner(command, 'chown core code', 0)
|
|
|
|
command = "chmod 640 /usr/local/CyberCP/CyberCP/settings.py"
|
|
Upgrade.executioner(command, 'chown core code', 0)
|
|
|
|
command = "chown root:cyberpanel /usr/local/CyberCP/CyberCP/settings.py"
|
|
Upgrade.executioner(command, 'chown core code', 0)
|
|
|
|
command = 'chmod +x /usr/local/CyberCP/CLManager/CLPackages.py'
|
|
Upgrade.executioner(command, 'chmod CLPackages', 0)
|
|
|
|
files = ['/etc/yum.repos.d/MariaDB.repo', '/etc/pdns/pdns.conf', '/etc/systemd/system/lscpd.service',
|
|
'/etc/pure-ftpd/pure-ftpd.conf', '/etc/pure-ftpd/pureftpd-pgsql.conf',
|
|
'/etc/pure-ftpd/pureftpd-mysql.conf', '/etc/pure-ftpd/pureftpd-ldap.conf',
|
|
'/etc/dovecot/dovecot.conf', '/usr/local/lsws/conf/httpd_config.xml',
|
|
'/usr/local/lsws/conf/modsec.conf', '/usr/local/lsws/conf/httpd.conf']
|
|
|
|
for items in files:
|
|
command = 'chmod 644 %s' % (items)
|
|
Upgrade.executioner(command, 'chown core code', 0)
|
|
|
|
impFile = ['/etc/pure-ftpd/pure-ftpd.conf', '/etc/pure-ftpd/pureftpd-pgsql.conf',
|
|
'/etc/pure-ftpd/pureftpd-mysql.conf', '/etc/pure-ftpd/pureftpd-ldap.conf',
|
|
'/etc/dovecot/dovecot.conf', '/etc/pdns/pdns.conf', '/etc/pure-ftpd/db/mysql.conf',
|
|
'/etc/powerdns/pdns.conf']
|
|
|
|
for items in impFile:
|
|
command = 'chmod 600 %s' % (items)
|
|
Upgrade.executioner(command, 'chown core code', 0)
|
|
|
|
command = 'chmod 640 /etc/postfix/*.cf'
|
|
subprocess.call(command, shell=True)
|
|
|
|
command = 'chmod 640 /etc/dovecot/*.conf'
|
|
subprocess.call(command, shell=True)
|
|
|
|
command = 'chmod 640 /etc/dovecot/dovecot-sql.conf.ext'
|
|
subprocess.call(command, shell=True)
|
|
|
|
fileM = ['/usr/local/lsws/FileManager/', '/usr/local/CyberCP/install/FileManager',
|
|
'/usr/local/CyberCP/serverStatus/litespeed/FileManager',
|
|
'/usr/local/lsws/Example/html/FileManager']
|
|
|
|
for items in fileM:
|
|
try:
|
|
shutil.rmtree(items)
|
|
except:
|
|
pass
|
|
|
|
command = 'chmod 755 /etc/pure-ftpd/'
|
|
subprocess.call(command, shell=True)
|
|
|
|
command = 'chmod 644 /etc/dovecot/dovecot.conf'
|
|
subprocess.call(command, shell=True)
|
|
|
|
command = 'chmod 644 /etc/postfix/main.cf'
|
|
subprocess.call(command, shell=True)
|
|
|
|
command = 'chmod 644 /etc/postfix/dynamicmaps.cf'
|
|
subprocess.call(command, shell=True)
|
|
|
|
command = 'chmod +x /usr/local/CyberCP/plogical/renew.py'
|
|
Upgrade.executioner(command, command, 0)
|
|
|
|
command = 'chmod +x /usr/local/CyberCP/CLManager/CLPackages.py'
|
|
Upgrade.executioner(command, command, 0)
|
|
|
|
clScripts = ['/usr/local/CyberCP/CLScript/panel_info.py',
|
|
'/usr/local/CyberCP/CLScript/CloudLinuxPackages.py',
|
|
'/usr/local/CyberCP/CLScript/CloudLinuxUsers.py',
|
|
'/usr/local/CyberCP/CLScript/CloudLinuxDomains.py'
|
|
, '/usr/local/CyberCP/CLScript/CloudLinuxResellers.py',
|
|
'/usr/local/CyberCP/CLScript/CloudLinuxAdmins.py',
|
|
'/usr/local/CyberCP/CLScript/CloudLinuxDB.py', '/usr/local/CyberCP/CLScript/UserInfo.py']
|
|
|
|
for items in clScripts:
|
|
command = 'chmod +x %s' % (items)
|
|
Upgrade.executioner(command, 0)
|
|
|
|
command = 'chmod 600 /usr/local/CyberCP/plogical/adminPass.py'
|
|
Upgrade.executioner(command, 0)
|
|
|
|
command = 'chmod 600 /etc/cagefs/exclude/cyberpanelexclude'
|
|
Upgrade.executioner(command, 0)
|
|
|
|
command = "find /usr/local/CyberCP/ -name '*.pyc' -delete"
|
|
Upgrade.executioner(command, 0)
|
|
|
|
if os.path.exists(Upgrade.CentOSPath) or os.path.exists(Upgrade.openEulerPath):
|
|
command = 'chown root:pdns /etc/pdns/pdns.conf'
|
|
Upgrade.executioner(command, 0)
|
|
|
|
command = 'chmod 640 /etc/pdns/pdns.conf'
|
|
Upgrade.executioner(command, 0)
|
|
else:
|
|
command = 'chown root:pdns /etc/powerdns/pdns.conf'
|
|
Upgrade.executioner(command, 0)
|
|
|
|
command = 'chmod 640 /etc/powerdns/pdns.conf'
|
|
Upgrade.executioner(command, 0)
|
|
|
|
command = 'chmod 640 /usr/local/lscp/cyberpanel/logs/access.log'
|
|
Upgrade.executioner(command, 0)
|
|
|
|
command = '/usr/local/lsws/lsphp83/bin/php /usr/local/CyberCP/public/snappymail.php'
|
|
Upgrade.executioner_silent(command, 'Configure SnappyMail')
|
|
|
|
command = 'chmod 600 /usr/local/CyberCP/public/snappymail.php'
|
|
Upgrade.executioner_silent(command, 'Secure SnappyMail config')
|
|
|
|
###
|
|
|
|
WriteToFile = open('/etc/fstab', 'a')
|
|
WriteToFile.write('proc /proc proc defaults,hidepid=2 0 0\n')
|
|
WriteToFile.close()
|
|
|
|
command = 'mount -o remount,rw,hidepid=2 /proc'
|
|
Upgrade.executioner(command, 0)
|
|
|
|
###
|
|
|
|
CentOSPath = '/etc/redhat-release'
|
|
openEulerPath = '/etc/openEuler-release'
|
|
|
|
if not os.path.exists(CentOSPath) or not os.path.exists(openEulerPath):
|
|
group = 'nobody'
|
|
else:
|
|
group = 'nogroup'
|
|
|
|
command = 'chown root:%s /usr/local/lsws/logs' % (group)
|
|
Upgrade.executioner(command, 0)
|
|
|
|
command = 'chmod 750 /usr/local/lsws/logs'
|
|
Upgrade.executioner(command, 0)
|
|
|
|
## symlink protection
|
|
|
|
writeToFile = open('/usr/lib/sysctl.d/50-default.conf', 'a')
|
|
writeToFile.writelines('fs.protected_hardlinks = 1\n')
|
|
writeToFile.writelines('fs.protected_symlinks = 1\n')
|
|
writeToFile.close()
|
|
|
|
command = 'sysctl --system'
|
|
Upgrade.executioner(command, 0)
|
|
|
|
command = 'chmod 700 %s' % ('/home/cyberpanel')
|
|
Upgrade.executioner(command, 0)
|
|
|
|
destPrivKey = "/usr/local/lscp/conf/key.pem"
|
|
|
|
command = 'chmod 600 %s' % (destPrivKey)
|
|
Upgrade.executioner(command, 0)
|
|
|
|
Upgrade.stdOut("Permissions updated.")
|
|
|
|
except Exception as e:
|
|
ErrorSanitizer.log_error_securely(e, 'fixPermissions')
|
|
Upgrade.stdOut("Failed to fix permissions [fixPermissions]")
|
|
|
|
@staticmethod
|
|
def AutoUpgradeAcme():
|
|
command = '/root/.acme.sh/acme.sh --upgrade --auto-upgrade'
|
|
Upgrade.executioner(command, command, 0)
|
|
command = '/root/.acme.sh/acme.sh --set-default-ca --server letsencrypt'
|
|
Upgrade.executioner(command, command, 0)
|
|
|
|
@staticmethod
|
|
def check_package_availability(package_name):
|
|
"""Check if a package is available in the repositories"""
|
|
try:
|
|
# Try to search for the package without installing
|
|
if os.path.exists('/etc/yum.repos.d/') or os.path.exists('/etc/dnf/dnf.conf'):
|
|
# RHEL-based systems
|
|
command = f"dnf search --quiet {package_name} 2>/dev/null | grep -q '^Last metadata expiration' || yum search --quiet {package_name} 2>/dev/null | head -1"
|
|
result = subprocess.run(command, shell=True, capture_output=True, text=True)
|
|
return result.returncode == 0
|
|
else:
|
|
# Ubuntu/Debian systems
|
|
command = f"apt-cache search {package_name} 2>/dev/null | head -1"
|
|
result = subprocess.run(command, shell=True, capture_output=True, text=True)
|
|
return result.returncode == 0 and result.stdout.strip() != ""
|
|
except Exception as e:
|
|
Upgrade.stdOut(f"Error checking package availability for {package_name}: {str(e)}", 0)
|
|
return False
|
|
|
|
@staticmethod
|
|
def is_almalinux9():
|
|
"""Check if running on AlmaLinux 9"""
|
|
if os.path.exists('/etc/almalinux-release'):
|
|
try:
|
|
with open('/etc/almalinux-release', 'r') as f:
|
|
content = f.read()
|
|
return 'release 9' in content
|
|
except:
|
|
return False
|
|
return False
|
|
|
|
@staticmethod
|
|
def fix_almalinux9_mariadb():
|
|
"""Fix AlmaLinux 9 MariaDB installation issues"""
|
|
if not Upgrade.is_almalinux9():
|
|
return
|
|
|
|
Upgrade.stdOut("Applying AlmaLinux 9 MariaDB fixes...", 1)
|
|
|
|
try:
|
|
# Disable problematic MariaDB MaxScale repository
|
|
Upgrade.stdOut("Disabling problematic MariaDB MaxScale repository...", 1)
|
|
command = "dnf config-manager --disable mariadb-maxscale 2>/dev/null || true"
|
|
subprocess.run(command, shell=True, capture_output=True)
|
|
|
|
# Remove problematic repository files
|
|
Upgrade.stdOut("Removing problematic repository files...", 1)
|
|
problematic_repos = [
|
|
'/etc/yum.repos.d/mariadb-maxscale.repo',
|
|
'/etc/yum.repos.d/mariadb-maxscale.repo.rpmnew'
|
|
]
|
|
for repo_file in problematic_repos:
|
|
if os.path.exists(repo_file):
|
|
os.remove(repo_file)
|
|
Upgrade.stdOut(f"Removed {repo_file}", 1)
|
|
|
|
# Clean DNF cache
|
|
Upgrade.stdOut("Cleaning DNF cache...", 1)
|
|
command = "dnf clean all"
|
|
subprocess.run(command, shell=True, capture_output=True)
|
|
|
|
# Install MariaDB from official repository
|
|
Upgrade.stdOut("Setting up official MariaDB repository...", 1)
|
|
command = "curl -sS https://downloads.mariadb.com/MariaDB/mariadb_repo_setup | bash -s -- --mariadb-server-version='12.1'"
|
|
result = subprocess.run(command, shell=True, capture_output=True, text=True)
|
|
if result.returncode != 0:
|
|
Upgrade.stdOut(f"Warning: MariaDB repo setup failed: {result.stderr}", 0)
|
|
|
|
# Install MariaDB packages
|
|
Upgrade.stdOut("Installing MariaDB packages...", 1)
|
|
mariadb_packages = "MariaDB-server MariaDB-client MariaDB-backup MariaDB-devel"
|
|
command = f"dnf install -y {mariadb_packages}"
|
|
result = subprocess.run(command, shell=True, capture_output=True, text=True)
|
|
if result.returncode != 0:
|
|
Upgrade.stdOut(f"Warning: MariaDB installation issues: {result.stderr}", 0)
|
|
|
|
# Start and enable MariaDB service
|
|
Upgrade.stdOut("Starting MariaDB service...", 1)
|
|
services = ['mariadb', 'mysql', 'mysqld']
|
|
for service in services:
|
|
try:
|
|
command = f"systemctl start {service}"
|
|
result = subprocess.run(command, shell=True, capture_output=True)
|
|
if result.returncode == 0:
|
|
command = f"systemctl enable {service}"
|
|
subprocess.run(command, shell=True, capture_output=True)
|
|
Upgrade.stdOut(f"MariaDB service started as {service}", 1)
|
|
break
|
|
except:
|
|
continue
|
|
|
|
Upgrade.stdOut("AlmaLinux 9 MariaDB fixes completed", 1)
|
|
|
|
except Exception as e:
|
|
Upgrade.stdOut(f"Error applying AlmaLinux 9 MariaDB fixes: {str(e)}", 0)
|
|
|
|
@staticmethod
|
|
def get_available_php_versions():
|
|
"""Get list of available PHP versions based on OS"""
|
|
# Check for AlmaLinux 9+ first
|
|
if os.path.exists('/etc/almalinux-release'):
|
|
try:
|
|
with open('/etc/almalinux-release', 'r') as f:
|
|
content = f.read()
|
|
if 'release 9' in content or 'release 10' in content:
|
|
Upgrade.stdOut("AlmaLinux 9+ detected - checking available PHP versions", 1)
|
|
# AlmaLinux 9+ doesn't have PHP 7.1, 7.2, 7.3
|
|
php_versions = ['74', '80', '81', '82', '83', '84', '85']
|
|
else:
|
|
php_versions = ['71', '72', '73', '74', '80', '81', '82', '83', '84', '85']
|
|
except:
|
|
php_versions = ['71', '72', '73', '74', '80', '81', '82', '83', '84', '85']
|
|
else:
|
|
# Check other OS versions
|
|
os_info = Upgrade.findOperatingSytem()
|
|
if os_info in [Ubuntu24, CENTOS8, Debian13]:
|
|
php_versions = ['74', '80', '81', '82', '83', '84', '85']
|
|
else:
|
|
php_versions = ['71', '72', '73', '74', '80', '81', '82', '83', '84', '85']
|
|
|
|
# Check availability of each version
|
|
available_versions = []
|
|
for version in php_versions:
|
|
if Upgrade.check_package_availability(f'lsphp{version}'):
|
|
available_versions.append(version)
|
|
else:
|
|
Upgrade.stdOut(f"PHP {version} not available on this OS", 0)
|
|
|
|
return available_versions
|
|
|
|
@staticmethod
|
|
def fixLiteSpeedConfig():
|
|
"""Fix LiteSpeed configuration issues by creating missing files and fixing permissions"""
|
|
try:
|
|
Upgrade.stdOut("Checking and fixing LiteSpeed configuration...", 1)
|
|
|
|
# Check if LiteSpeed is installed
|
|
if not os.path.exists('/usr/local/lsws'):
|
|
Upgrade.stdOut("LiteSpeed not found at /usr/local/lsws", 0)
|
|
return
|
|
|
|
# Fix LiteSpeed permissions first
|
|
Upgrade.stdOut("Fixing LiteSpeed permissions...", 1)
|
|
litespeed_dirs = ['/usr/local/lsws', '/usr/local/lscp', '/usr/local/CyberCP']
|
|
for directory in litespeed_dirs:
|
|
if os.path.exists(directory):
|
|
command = f'chown -R lscpd:lscpd {directory}'
|
|
Upgrade.executioner(command, f'Fix ownership for {directory}', 0)
|
|
|
|
command = f'chmod -R 755 {directory}'
|
|
Upgrade.executioner(command, f'Fix permissions for {directory}', 0)
|
|
|
|
# Create missing configuration files
|
|
config_files = [
|
|
"/usr/local/lsws/conf/httpd_config.xml",
|
|
"/usr/local/lsws/conf/httpd.conf",
|
|
"/usr/local/lscp/conf/httpd_config.xml",
|
|
"/usr/local/lscp/conf/httpd.conf"
|
|
]
|
|
|
|
for config_file in config_files:
|
|
if not os.path.exists(config_file):
|
|
Upgrade.stdOut(f"Missing LiteSpeed config: {config_file}", 0)
|
|
|
|
# Create directory if it doesn't exist
|
|
os.makedirs(os.path.dirname(config_file), exist_ok=True)
|
|
|
|
# Create minimal config file
|
|
if config_file.endswith('httpd_config.xml'):
|
|
with open(config_file, 'w') as f:
|
|
f.write('<?xml version="1.0" encoding="UTF-8"?>\n')
|
|
f.write('<httpServerConfig>\n')
|
|
f.write(' <!-- Minimal LiteSpeed configuration -->\n')
|
|
f.write(' <listener>\n')
|
|
f.write(' <name>Default</name>\n')
|
|
f.write(' <address>*:8088</address>\n')
|
|
f.write(' </listener>\n')
|
|
f.write('</httpServerConfig>\n')
|
|
elif config_file.endswith('httpd.conf'):
|
|
with open(config_file, 'w') as f:
|
|
f.write('# Minimal LiteSpeed HTTP configuration\n')
|
|
f.write('# This file will be updated by CyberPanel\n')
|
|
|
|
# Set proper permissions
|
|
os.chmod(config_file, 0o644)
|
|
command = f'chown lscpd:lscpd {config_file}'
|
|
Upgrade.executioner(command, f'Fix config ownership: {config_file}', 0)
|
|
|
|
Upgrade.stdOut(f"Created minimal config: {config_file}", 1)
|
|
else:
|
|
Upgrade.stdOut(f"LiteSpeed config exists: {config_file}", 1)
|
|
|
|
# Create PHP socket directory if it doesn't exist
|
|
php_sock_dir = '/var/run/php/'
|
|
if not os.path.exists(php_sock_dir):
|
|
Upgrade.stdOut("Creating PHP socket directory...", 1)
|
|
os.makedirs(php_sock_dir, exist_ok=True)
|
|
command = f'chmod 755 {php_sock_dir}'
|
|
Upgrade.executioner(command, 'Fix PHP socket directory permissions', 0)
|
|
|
|
# Set ownership based on distribution
|
|
osType = Upgrade.decideDistro()
|
|
if osType in [Upgrade.centos, Upgrade.cent8, Upgrade.cloudlinux]:
|
|
command = f'chown apache:apache {php_sock_dir}'
|
|
else:
|
|
command = f'chown www-data:www-data {php_sock_dir}'
|
|
Upgrade.executioner(command, 'Fix PHP socket directory ownership', 0)
|
|
|
|
# Restart LiteSpeed services to apply changes
|
|
Upgrade.stdOut("Restarting LiteSpeed services...", 1)
|
|
litespeed_services = ['lsws', 'lscpd']
|
|
for service in litespeed_services:
|
|
command = f'systemctl restart {service}'
|
|
Upgrade.executioner(command, f'Restart {service}', 0)
|
|
|
|
command = f'systemctl enable {service}'
|
|
Upgrade.executioner(command, f'Enable {service}', 0)
|
|
|
|
# Verify service is running
|
|
command = f'systemctl is-active {service}'
|
|
try:
|
|
result = subprocess.run(command, shell=True, capture_output=True, text=True)
|
|
if result.stdout.strip() == 'active':
|
|
Upgrade.stdOut(f"{service} is running successfully", 1)
|
|
else:
|
|
Upgrade.stdOut(f"{service} status: {result.stdout.strip()}", 0)
|
|
except:
|
|
Upgrade.stdOut(f"Could not verify {service} status", 0)
|
|
|
|
except Exception as e:
|
|
Upgrade.stdOut(f"Error fixing LiteSpeed config: {str(e)}", 0)
|
|
|
|
@staticmethod
|
|
def fixServiceConfiguration():
|
|
"""Comprehensive service configuration fix for common 503 error causes"""
|
|
try:
|
|
Upgrade.stdOut("Applying comprehensive service configuration fixes...", 1)
|
|
|
|
# Upgrade pip first for better package compatibility
|
|
Upgrade.upgradePip()
|
|
|
|
# Fix PowerDNS configuration
|
|
Upgrade.fixPowerDNSConfig()
|
|
|
|
# Fix Pure-FTPd configuration
|
|
Upgrade.fixPureFTPdConfig()
|
|
|
|
# Fix database connectivity
|
|
Upgrade.fixDatabaseConnectivity()
|
|
|
|
# Fix PHP-FPM services
|
|
Upgrade.fixPHPFPMServices()
|
|
|
|
# Final service restart and verification
|
|
Upgrade.restartAndVerifyServices()
|
|
|
|
except Exception as e:
|
|
Upgrade.stdOut(f"Error in service configuration fix: {str(e)}", 0)
|
|
|
|
@staticmethod
|
|
def upgradePip():
|
|
"""Upgrade pip to latest version for better package compatibility"""
|
|
try:
|
|
Upgrade.stdOut("Upgrading pip to latest version...", 1)
|
|
|
|
# Determine the correct Python path
|
|
python_paths = [
|
|
"/usr/local/CyberPanel/bin/python",
|
|
"/usr/local/CyberCP/bin/python",
|
|
"/usr/bin/python3",
|
|
"/usr/local/bin/python3"
|
|
]
|
|
|
|
python_path = None
|
|
for path in python_paths:
|
|
if os.path.exists(path):
|
|
python_path = path
|
|
break
|
|
|
|
if not python_path:
|
|
Upgrade.stdOut("No Python executable found for pip upgrade", 0)
|
|
return False
|
|
|
|
# Upgrade pip and essential packages
|
|
upgrade_command = f"{python_path} -m pip install --upgrade pip setuptools wheel packaging"
|
|
result = Upgrade.executioner(upgrade_command, "Upgrade pip", 0)
|
|
|
|
if result == 1:
|
|
Upgrade.stdOut("pip upgraded successfully", 1)
|
|
return True
|
|
else:
|
|
Upgrade.stdOut("WARNING: pip upgrade failed, continuing with current version", 0)
|
|
return False
|
|
|
|
except Exception as e:
|
|
Upgrade.stdOut(f"Error upgrading pip: {str(e)}", 0)
|
|
return False
|
|
|
|
@staticmethod
|
|
def fixPowerDNSConfig():
|
|
"""Fix PowerDNS configuration issues"""
|
|
try:
|
|
Upgrade.stdOut("Fixing PowerDNS configuration...", 1)
|
|
|
|
# Check if PowerDNS is installed
|
|
if not os.path.exists('/home/cyberpanel/powerdns'):
|
|
Upgrade.stdOut("PowerDNS not enabled, skipping...", 1)
|
|
return
|
|
|
|
# Determine correct service name
|
|
pdns_service = None
|
|
result = subprocess.run(['systemctl', 'list-unit-files'], capture_output=True, text=True)
|
|
if 'pdns.service' in result.stdout:
|
|
pdns_service = 'pdns'
|
|
elif 'powerdns.service' in result.stdout:
|
|
pdns_service = 'powerdns'
|
|
|
|
if not pdns_service:
|
|
Upgrade.stdOut("PowerDNS service not found", 0)
|
|
return
|
|
|
|
# Fix PowerDNS configuration files
|
|
config_files = ['/etc/pdns/pdns.conf', '/etc/powerdns/pdns.conf']
|
|
for config_file in config_files:
|
|
if os.path.exists(config_file):
|
|
Upgrade.stdOut(f"Configuring PowerDNS: {config_file}", 1)
|
|
|
|
# Read existing content
|
|
with open(config_file, 'r') as f:
|
|
content = f.read()
|
|
|
|
# Add missing configuration if not present
|
|
if 'gmysql-password=' not in content:
|
|
content += '\ngmysql-password=cyberpanel\n'
|
|
if 'launch=' not in content:
|
|
content += 'launch=gmysql\n'
|
|
|
|
# Write back the configuration
|
|
with open(config_file, 'w') as f:
|
|
f.write(content)
|
|
|
|
# Set proper permissions
|
|
os.chmod(config_file, 0o644)
|
|
command = f'chown root:root {config_file}'
|
|
Upgrade.executioner(command, f'Fix PowerDNS config ownership', 0)
|
|
break
|
|
|
|
# Restart PowerDNS service
|
|
command = f'systemctl restart {pdns_service}'
|
|
Upgrade.executioner(command, f'Restart PowerDNS', 0)
|
|
|
|
command = f'systemctl enable {pdns_service}'
|
|
Upgrade.executioner(command, f'Enable PowerDNS', 0)
|
|
|
|
# Verify service is running
|
|
command = f'systemctl is-active {pdns_service}'
|
|
result = subprocess.run(command, shell=True, capture_output=True, text=True)
|
|
if result.stdout.strip() == 'active':
|
|
Upgrade.stdOut("PowerDNS is running successfully", 1)
|
|
else:
|
|
Upgrade.stdOut(f"PowerDNS status: {result.stdout.strip()}", 0)
|
|
|
|
except Exception as e:
|
|
Upgrade.stdOut(f"Error fixing PowerDNS config: {str(e)}", 0)
|
|
|
|
@staticmethod
|
|
def fixPureFTPdConfig():
|
|
"""Fix Pure-FTPd configuration issues"""
|
|
try:
|
|
Upgrade.stdOut("Fixing Pure-FTPd configuration...", 1)
|
|
|
|
# Check if Pure-FTPd is installed
|
|
if not os.path.exists('/home/cyberpanel/pureftpd'):
|
|
Upgrade.stdOut("Pure-FTPd not enabled, skipping...", 1)
|
|
return
|
|
|
|
# Determine correct service name
|
|
ftp_service = None
|
|
result = subprocess.run(['systemctl', 'list-unit-files'], capture_output=True, text=True)
|
|
if 'pure-ftpd.service' in result.stdout:
|
|
ftp_service = 'pure-ftpd'
|
|
elif 'pureftpd.service' in result.stdout:
|
|
ftp_service = 'pureftpd'
|
|
|
|
if not ftp_service:
|
|
Upgrade.stdOut("Pure-FTPd service not found", 0)
|
|
return
|
|
|
|
# Fix Pure-FTPd configuration files
|
|
config_files = ['/etc/pure-ftpd/pureftpd-mysql.conf', '/etc/pure-ftpd/db/mysql.conf']
|
|
for config_file in config_files:
|
|
if os.path.exists(config_file):
|
|
Upgrade.stdOut(f"Configuring Pure-FTPd: {config_file}", 1)
|
|
|
|
# Fix MySQL password configuration
|
|
command = f"sed -i 's/MYSQLPassword.*/MYSQLPassword cyberpanel/' {config_file}"
|
|
Upgrade.executioner(command, f'Fix Pure-FTPd MySQL password', 0)
|
|
|
|
# Fix MySQL crypt method for Ubuntu 24.04 compatibility
|
|
command = f"sed -i 's/MYSQLCrypt md5/MYSQLCrypt crypt/g' {config_file}"
|
|
Upgrade.executioner(command, f'Fix Pure-FTPd MySQL crypt method', 0)
|
|
|
|
# Set proper permissions
|
|
os.chmod(config_file, 0o644)
|
|
command = f'chown root:root {config_file}'
|
|
Upgrade.executioner(command, f'Fix Pure-FTPd config ownership', 0)
|
|
|
|
# Restart Pure-FTPd service
|
|
command = f'systemctl restart {ftp_service}'
|
|
Upgrade.executioner(command, f'Restart Pure-FTPd', 0)
|
|
|
|
command = f'systemctl enable {ftp_service}'
|
|
Upgrade.executioner(command, f'Enable Pure-FTPd', 0)
|
|
|
|
# Verify service is running
|
|
command = f'systemctl is-active {ftp_service}'
|
|
result = subprocess.run(command, shell=True, capture_output=True, text=True)
|
|
if result.stdout.strip() == 'active':
|
|
Upgrade.stdOut("Pure-FTPd is running successfully", 1)
|
|
else:
|
|
Upgrade.stdOut(f"Pure-FTPd status: {result.stdout.strip()}", 0)
|
|
|
|
except Exception as e:
|
|
Upgrade.stdOut(f"Error fixing Pure-FTPd config: {str(e)}", 0)
|
|
|
|
@staticmethod
|
|
def fixDatabaseConnectivity():
|
|
"""Fix database connectivity issues"""
|
|
try:
|
|
Upgrade.stdOut("Fixing database connectivity...", 1)
|
|
|
|
# Determine database service name
|
|
db_service = None
|
|
result = subprocess.run(['systemctl', 'list-unit-files'], capture_output=True, text=True)
|
|
if 'mariadb.service' in result.stdout:
|
|
db_service = 'mariadb'
|
|
elif 'mysql.service' in result.stdout:
|
|
db_service = 'mysql'
|
|
elif 'mysqld.service' in result.stdout:
|
|
db_service = 'mysqld'
|
|
|
|
if not db_service:
|
|
Upgrade.stdOut("Database service not found", 0)
|
|
return
|
|
|
|
# Ensure database service is running
|
|
command = f'systemctl restart {db_service}'
|
|
Upgrade.executioner(command, f'Restart database service', 0)
|
|
|
|
command = f'systemctl enable {db_service}'
|
|
Upgrade.executioner(command, f'Enable database service', 0)
|
|
|
|
# Wait for database to be ready
|
|
Upgrade.stdOut("Waiting for database to be ready...", 1)
|
|
max_attempts = 30
|
|
for attempt in range(max_attempts):
|
|
try:
|
|
result = subprocess.run(['mysqladmin', 'ping', '-h', 'localhost', '--silent'],
|
|
capture_output=True)
|
|
if result.returncode == 0:
|
|
Upgrade.stdOut("Database is ready", 1)
|
|
break
|
|
except:
|
|
pass
|
|
time.sleep(2)
|
|
|
|
# Ensure cyberpanel database exists
|
|
try:
|
|
result = subprocess.run(['mysql', '-e', 'USE cyberpanel;'], capture_output=True)
|
|
if result.returncode != 0:
|
|
Upgrade.stdOut("Creating cyberpanel database...", 1)
|
|
commands = [
|
|
'mysql -e "CREATE DATABASE IF NOT EXISTS cyberpanel;"',
|
|
'mysql -e "CREATE USER IF NOT EXISTS \'cyberpanel\'@\'localhost\' IDENTIFIED BY \'cyberpanel\';"',
|
|
'mysql -e "GRANT ALL PRIVILEGES ON cyberpanel.* TO \'cyberpanel\'@\'localhost\';"',
|
|
'mysql -e "FLUSH PRIVILEGES;"'
|
|
]
|
|
for cmd in commands:
|
|
Upgrade.executioner(cmd, 'Setup cyberpanel database', 0)
|
|
except:
|
|
Upgrade.stdOut("Could not verify cyberpanel database", 0)
|
|
|
|
except Exception as e:
|
|
Upgrade.stdOut(f"Error fixing database connectivity: {str(e)}", 0)
|
|
|
|
@staticmethod
|
|
def fixPHPFPMServices():
|
|
"""Fix PHP-FPM services"""
|
|
try:
|
|
Upgrade.stdOut("Fixing PHP-FPM services...", 1)
|
|
|
|
# Get available PHP versions
|
|
php_versions = Upgrade.get_available_php_versions()
|
|
|
|
for version in php_versions:
|
|
# Determine FPM service name based on distribution
|
|
osType = Upgrade.decideDistro()
|
|
if osType in [Upgrade.centos, Upgrade.cent8, Upgrade.cloudlinux]:
|
|
fpm_service = f'php{version}-php-fpm'
|
|
else:
|
|
fpm_service = f'php{version}-fpm'
|
|
|
|
# Check if service exists and restart it
|
|
result = subprocess.run(['systemctl', 'list-unit-files'], capture_output=True, text=True)
|
|
if f'{fpm_service}.service' in result.stdout:
|
|
Upgrade.stdOut(f"Restarting PHP-FPM {version}...", 1)
|
|
command = f'systemctl restart {fpm_service}'
|
|
Upgrade.executioner(command, f'Restart PHP-FPM {version}', 0)
|
|
|
|
command = f'systemctl enable {fpm_service}'
|
|
Upgrade.executioner(command, f'Enable PHP-FPM {version}', 0)
|
|
|
|
# Verify service is running
|
|
command = f'systemctl is-active {fpm_service}'
|
|
result = subprocess.run(command, shell=True, capture_output=True, text=True)
|
|
if result.stdout.strip() == 'active':
|
|
Upgrade.stdOut(f"PHP-FPM {version} is running", 1)
|
|
else:
|
|
Upgrade.stdOut(f"PHP-FPM {version} status: {result.stdout.strip()}", 0)
|
|
|
|
except Exception as e:
|
|
Upgrade.stdOut(f"Error fixing PHP-FPM services: {str(e)}", 0)
|
|
|
|
@staticmethod
|
|
def restartAndVerifyServices():
|
|
"""Restart and verify all critical services"""
|
|
try:
|
|
Upgrade.stdOut("Restarting and verifying critical services...", 1)
|
|
|
|
# Reload systemd daemon
|
|
command = 'systemctl daemon-reload'
|
|
Upgrade.executioner(command, 'Reload systemd daemon', 0)
|
|
|
|
# Restart critical services in order
|
|
critical_services = ['lsws', 'lscpd']
|
|
all_services_ok = True
|
|
|
|
for service in critical_services:
|
|
# Check if service exists before trying to manage it
|
|
check_command = f'systemctl list-unit-files | grep -q "{service}.service"'
|
|
result = subprocess.run(check_command, shell=True, capture_output=True)
|
|
|
|
if result.returncode != 0:
|
|
Upgrade.stdOut(f"Service {service} not found, skipping management", 1)
|
|
continue
|
|
|
|
Upgrade.stdOut(f"Restarting {service}...", 1)
|
|
command = f'systemctl restart {service}'
|
|
Upgrade.executioner(command, f'Restart {service}', 0)
|
|
|
|
command = f'systemctl enable {service}'
|
|
Upgrade.executioner(command, f'Enable {service}', 0)
|
|
|
|
# Verify service is running
|
|
command = f'systemctl is-active {service}'
|
|
result = subprocess.run(command, shell=True, capture_output=True, text=True)
|
|
if result.stdout.strip() == 'active':
|
|
Upgrade.stdOut(f"✓ {service} is running successfully", 1)
|
|
else:
|
|
Upgrade.stdOut(f"✗ {service} is not running (status: {result.stdout.strip()})", 0)
|
|
all_services_ok = False
|
|
|
|
if all_services_ok:
|
|
Upgrade.stdOut("All critical services are running successfully!", 1)
|
|
Upgrade.stdOut("CyberPanel should now be accessible at https://your-server-ip:8090", 1)
|
|
else:
|
|
Upgrade.stdOut("Some critical services are not running properly", 0)
|
|
Upgrade.stdOut("Please check the logs and consider a server restart", 0)
|
|
|
|
except Exception as e:
|
|
Upgrade.stdOut(f"Error in service verification: {str(e)}", 0)
|
|
|
|
@staticmethod
|
|
def installPHP73():
|
|
try:
|
|
Upgrade.stdOut("Installing PHP versions based on OS compatibility...", 1)
|
|
|
|
# Get available PHP versions
|
|
available_versions = Upgrade.get_available_php_versions()
|
|
|
|
if not available_versions:
|
|
Upgrade.stdOut("No PHP versions available for installation", 0)
|
|
return
|
|
|
|
Upgrade.stdOut(f"Installing available PHP versions: {', '.join(available_versions)}", 1)
|
|
|
|
for version in available_versions:
|
|
try:
|
|
if version in ['74']:
|
|
# PHP 7.4 only (legacy support) with specific extensions
|
|
if Upgrade.installedOutput.find(f'lsphp{version}') == -1:
|
|
extensions = ['json', 'xmlrpc', 'xml', 'tidy', 'soap', 'snmp', 'recode', 'pspell', 'process', 'pgsql', 'pear', 'pdo', 'opcache', 'odbc', 'mysqlnd', 'mcrypt', 'mbstring', 'ldap', 'intl', 'imap', 'gmp', 'gd', 'enchant', 'dba', 'common', 'bcmath']
|
|
package_list = f"lsphp{version} " + " ".join([f"lsphp{version}-{ext}" for ext in extensions])
|
|
command = f"yum install -y {package_list}"
|
|
Upgrade.executioner(command, f'Install PHP {version}', 0)
|
|
elif version in ['80', '81', '82', '83', '84', '85']:
|
|
# PHP 8.x versions (including 8.5 beta)
|
|
if Upgrade.installedOutput.find(f'lsphp{version}') == -1:
|
|
command = f"yum install lsphp{version}* -y"
|
|
subprocess.call(command, shell=True)
|
|
Upgrade.stdOut(f"Installed PHP {version}", 1)
|
|
|
|
except Exception as e:
|
|
Upgrade.stdOut(f"Error installing PHP {version}: {str(e)}", 0)
|
|
continue
|
|
|
|
except:
|
|
command = 'DEBIAN_FRONTEND=noninteractive apt-get -y install ' \
|
|
'lsphp7? lsphp7?-common lsphp7?-curl lsphp7?-dev lsphp7?-imap lsphp7?-intl lsphp7?-json ' \
|
|
'lsphp7?-ldap lsphp7?-mysql lsphp7?-opcache lsphp7?-pspell lsphp7?-recode ' \
|
|
'lsphp7?-sqlite3 lsphp7?-tidy'
|
|
Upgrade.executioner(command, 'Install PHP 7.x', 0)
|
|
|
|
command = 'DEBIAN_FRONTEND=noninteractive apt-get -y install lsphp80*'
|
|
os.system(command)
|
|
|
|
command = 'DEBIAN_FRONTEND=noninteractive apt-get -y install lsphp81*'
|
|
os.system(command)
|
|
|
|
command = 'DEBIAN_FRONTEND=noninteractive apt-get -y install lsphp82*'
|
|
os.system(command)
|
|
|
|
command = 'DEBIAN_FRONTEND=noninteractive apt-get -y install lsphp83*'
|
|
os.system(command)
|
|
|
|
command = 'DEBIAN_FRONTEND=noninteractive apt-get -y install lsphp84*'
|
|
os.system(command)
|
|
|
|
command = 'DEBIAN_FRONTEND=noninteractive apt-get -y install lsphp85*'
|
|
os.system(command)
|
|
|
|
CentOSPath = '/etc/redhat-release'
|
|
openEulerPath = '/etc/openEuler-release'
|
|
|
|
# if not os.path.exists(CentOSPath) or not os.path.exists(openEulerPath):
|
|
# command = 'cp /usr/local/lsws/lsphp71/bin/php /usr/bin/'
|
|
# Upgrade.executioner(command, 'Set default PHP 7.0, 0')
|
|
|
|
@staticmethod
|
|
def someDirectories():
|
|
command = "mkdir -p /usr/local/lscpd/admin/"
|
|
Upgrade.executioner(command, 0)
|
|
|
|
command = "mkdir -p /usr/local/lscp/cyberpanel/logs"
|
|
Upgrade.executioner(command, 0)
|
|
|
|
@staticmethod
|
|
def upgradeDovecot():
|
|
try:
|
|
Upgrade.stdOut("Upgrading Dovecot..")
|
|
CentOSPath = '/etc/redhat-release'
|
|
openEulerPath = '/etc/openEuler-release'
|
|
|
|
dovecotConfPath = '/etc/dovecot/'
|
|
postfixConfPath = '/etc/postfix/'
|
|
|
|
## Take backup of configurations
|
|
|
|
configbackups = '/home/cyberpanel/configbackups'
|
|
|
|
command = 'mkdir %s' % (configbackups)
|
|
Upgrade.executioner(command, 0)
|
|
|
|
command = 'cp -pR %s %s' % (dovecotConfPath, configbackups)
|
|
Upgrade.executioner(command, 0)
|
|
|
|
command = 'cp -pR %s %s' % (postfixConfPath, configbackups)
|
|
Upgrade.executioner(command, 0)
|
|
|
|
if Upgrade.FindOperatingSytem() == CENTOS8 or Upgrade.FindOperatingSytem() == CENTOS7 or Upgrade.FindOperatingSytem() == openEuler22 or Upgrade.FindOperatingSytem() == openEuler20:
|
|
|
|
command = "yum makecache -y"
|
|
Upgrade.executioner(command, 0)
|
|
|
|
command = "yum update -y"
|
|
Upgrade.executioner(command, 0)
|
|
|
|
if Upgrade.FindOperatingSytem() == CENTOS8:
|
|
command = 'dnf remove dovecot23 dovecot23-mysql -y'
|
|
Upgrade.executioner(command, 0)
|
|
|
|
command = 'dnf install --enablerepo=gf-plus dovecot23 dovecot23-mysql -y'
|
|
Upgrade.executioner(command, 0)
|
|
|
|
import django
|
|
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "CyberCP.settings")
|
|
django.setup()
|
|
from mailServer.models import EUsers
|
|
|
|
Upgrade.stdOut("Upgrading passwords...")
|
|
for items in EUsers.objects.all():
|
|
if items.password.find('CRYPT') > -1:
|
|
continue
|
|
command = 'doveadm pw -p %s' % (items.password)
|
|
try:
|
|
items.password = subprocess.check_output(shlex.split(command)).decode("utf-8").strip('\n')
|
|
except Exception as e:
|
|
Upgrade.stdOut(f"Error hashing password for {items.email}: {str(e)}")
|
|
continue
|
|
items.save()
|
|
|
|
command = "systemctl restart dovecot"
|
|
Upgrade.executioner(command, 0)
|
|
|
|
### Postfix Upgrade
|
|
|
|
command = 'yum remove postfix -y'
|
|
Upgrade.executioner(command, 0)
|
|
|
|
command = 'yum clean all'
|
|
Upgrade.executioner(command, 0)
|
|
|
|
if Upgrade.FindOperatingSytem() == CENTOS7:
|
|
command = 'yum makecache fast'
|
|
else:
|
|
command = 'yum makecache -y'
|
|
|
|
Upgrade.executioner(command, 0)
|
|
|
|
if Upgrade.FindOperatingSytem() == CENTOS7:
|
|
command = 'yum install --enablerepo=gf-plus -y postfix3 postfix3-ldap postfix3-mysql postfix3-pcre'
|
|
else:
|
|
command = 'dnf install --enablerepo=gf-plus postfix3 postfix3-mysql -y'
|
|
|
|
Upgrade.executioner(command, 0)
|
|
|
|
### Restore dovecot/postfix conf
|
|
|
|
command = 'cp -pR %s/dovecot/ /etc/' % (configbackups)
|
|
Upgrade.executioner(command, 0)
|
|
|
|
command = 'cp -pR %s/postfix/ /etc/' % (configbackups)
|
|
Upgrade.executioner(command, 0)
|
|
|
|
## Restored
|
|
|
|
command = 'systemctl restart postfix'
|
|
Upgrade.executioner(command, 0)
|
|
elif Upgrade.FindOperatingSytem() == Ubuntu20 or Upgrade.FindOperatingSytem() == Ubuntu22 or Upgrade.FindOperatingSytem() == Ubuntu24 or Upgrade.FindOperatingSytem() == Debian11 or Upgrade.FindOperatingSytem() == Debian12 or Upgrade.FindOperatingSytem() == Debian13:
|
|
|
|
debPath = '/etc/apt/sources.list.d/dovecot.list'
|
|
# writeToFile = open(debPath, 'w')
|
|
# writeToFile.write('deb https://repo.dovecot.org/ce-2.3-latest/ubuntu/focal focal main\n')
|
|
# writeToFile.close()
|
|
#
|
|
# command = "apt update -y"
|
|
# Upgrade.executioner(command, command)
|
|
#
|
|
# command = 'dpkg --configure -a'
|
|
# subprocess.call(command, shell=True)
|
|
#
|
|
# command = 'apt --fix-broken install -y'
|
|
# subprocess.call(command, shell=True)
|
|
#
|
|
# command = 'DEBIAN_FRONTEND=noninteractive DEBIAN_PRIORITY=critical apt -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" upgrade -y'
|
|
# subprocess.call(command, shell=True)
|
|
|
|
dovecotConf = '/etc/dovecot/dovecot.conf'
|
|
|
|
try:
|
|
dovecotContent = open(dovecotConf, 'r').read()
|
|
except Exception as e:
|
|
Upgrade.stdOut(f"Error reading dovecot config: {str(e)}")
|
|
dovecotContent = ""
|
|
|
|
if dovecotContent and dovecotContent.find('service stats') == -1:
|
|
writeToFile = open(dovecotConf, 'a')
|
|
|
|
content = """\nservice stats {
|
|
unix_listener stats-reader {
|
|
user = vmail
|
|
group = vmail
|
|
mode = 0660
|
|
}
|
|
unix_listener stats-writer {
|
|
user = vmail
|
|
group = vmail
|
|
mode = 0660
|
|
}
|
|
}\n"""
|
|
|
|
writeToFile.write(content)
|
|
writeToFile.close()
|
|
|
|
# Fix mailbox auto-creation issue
|
|
if dovecotContent and dovecotContent.find('lda_mailbox_autocreate') == -1:
|
|
Upgrade.stdOut("Enabling mailbox auto-creation in dovecot...")
|
|
|
|
# Add mailbox auto-creation settings to protocol lda section
|
|
try:
|
|
dovecotContent = open(dovecotConf, 'r').read()
|
|
except Exception as e:
|
|
Upgrade.stdOut(f"Error reading dovecot config: {str(e)}")
|
|
dovecotContent = ""
|
|
|
|
if dovecotContent and dovecotContent.find('protocol lda') > -1:
|
|
# Update existing protocol lda section
|
|
import re
|
|
pattern = r'(protocol lda\s*{[^}]*)'
|
|
replacement = r'\1\n lda_mailbox_autocreate = yes\n lda_mailbox_autosubscribe = yes'
|
|
if isinstance(dovecotContent, str):
|
|
dovecotContent = re.sub(pattern, replacement, dovecotContent)
|
|
|
|
writeToFile = open(dovecotConf, 'w')
|
|
writeToFile.write(dovecotContent)
|
|
writeToFile.close()
|
|
else:
|
|
# Add new protocol lda section
|
|
writeToFile = open(dovecotConf, 'a')
|
|
content = """\nprotocol lda {
|
|
lda_mailbox_autocreate = yes
|
|
lda_mailbox_autosubscribe = yes
|
|
}\n"""
|
|
writeToFile.write(content)
|
|
writeToFile.close()
|
|
|
|
command = 'systemctl restart dovecot'
|
|
Upgrade.executioner(command, command, 0)
|
|
|
|
command = 'rm -rf %s' % (configbackups)
|
|
Upgrade.executioner(command, command, 0)
|
|
|
|
Upgrade.stdOut("Dovecot upgraded.")
|
|
|
|
except Exception as e:
|
|
ErrorSanitizer.log_error_securely(e, 'upgradeDovecot')
|
|
Upgrade.stdOut("Failed to upgrade Dovecot [upgradeDovecot]")
|
|
|
|
@staticmethod
|
|
def installRestic():
|
|
CentOSPath = '/etc/redhat-release'
|
|
openEulerPath = '/etc/openEuler-release'
|
|
|
|
if os.path.exists(CentOSPath) or os.path.exists(openEulerPath):
|
|
if Upgrade.installedOutput.find('restic') == -1:
|
|
command = 'yum install restic -y'
|
|
Upgrade.executioner(command, 'Install Restic')
|
|
command = 'restic self-update'
|
|
Upgrade.executioner(command, 'Install Restic')
|
|
else:
|
|
|
|
if Upgrade.installedOutput.find('restic/bionic,now 0.8') == -1:
|
|
command = 'apt-get update -y'
|
|
Upgrade.executioner(command, 'Install Restic')
|
|
|
|
command = 'apt-get install restic -y'
|
|
Upgrade.executioner(command, 'Install Restic')
|
|
|
|
command = 'restic self-update'
|
|
Upgrade.executioner(command, 'Install Restic')
|
|
|
|
@staticmethod
|
|
def UpdateMaxSSLCons():
|
|
command = "sed -i 's|<maxConnections>2000</maxConnections>|<maxConnections>10000</maxConnections>|g' /usr/local/lsws/conf/httpd_config.xml"
|
|
Upgrade.executioner(command, 0)
|
|
|
|
command = "sed -i 's|<maxSSLConnections>200</maxSSLConnections>|<maxSSLConnections>10000</maxSSLConnections>|g' /usr/local/lsws/conf/httpd_config.xml"
|
|
Upgrade.executioner(command, 0)
|
|
|
|
@staticmethod
|
|
def installCLScripts():
|
|
try:
|
|
|
|
CentOSPath = '/etc/redhat-release'
|
|
openEulerPath = '/etc/openEuler-release'
|
|
|
|
if os.path.exists(CentOSPath) or os.path.exists(openEulerPath):
|
|
command = 'mkdir -p /opt/cpvendor/etc/'
|
|
Upgrade.executioner(command, 0)
|
|
|
|
content = """[integration_scripts]
|
|
|
|
panel_info = /usr/local/CyberCP/CLScript/panel_info.py
|
|
packages = /usr/local/CyberCP/CLScript/CloudLinuxPackages.py
|
|
users = /usr/local/CyberCP/CLScript/CloudLinuxUsers.py
|
|
domains = /usr/local/CyberCP/CLScript/CloudLinuxDomains.py
|
|
resellers = /usr/local/CyberCP/CLScript/CloudLinuxResellers.py
|
|
admins = /usr/local/CyberCP/CLScript/CloudLinuxAdmins.py
|
|
db_info = /usr/local/CyberCP/CLScript/CloudLinuxDB.py
|
|
|
|
[lvemanager_config]
|
|
ui_user_info = /usr/local/CyberCP/CLScript/UserInfo.py
|
|
base_path = /usr/local/lvemanager
|
|
run_service = 1
|
|
service_port = 9000
|
|
"""
|
|
|
|
if not os.path.exists('/opt/cpvendor/etc/integration.ini'):
|
|
writeToFile = open('/opt/cpvendor/etc/integration.ini', 'w')
|
|
writeToFile.write(content)
|
|
writeToFile.close()
|
|
|
|
command = 'mkdir -p /etc/cagefs/exclude'
|
|
Upgrade.executioner(command, command, 0)
|
|
|
|
content = """cyberpanel
|
|
docker
|
|
ftpuser
|
|
lscpd
|
|
opendkim
|
|
pdns
|
|
vmail
|
|
"""
|
|
|
|
writeToFile = open('/etc/cagefs/exclude/cyberpanelexclude', 'w')
|
|
writeToFile.write(content)
|
|
writeToFile.close()
|
|
|
|
except:
|
|
pass
|
|
|
|
@staticmethod
|
|
def runSomeImportantBash():
|
|
|
|
# Remove invalid crons from /etc/crontab Reference: https://github.com/usmannasir/cyberpanel/issues/216
|
|
command = """sed -i '/CyberCP/d' /etc/crontab"""
|
|
Upgrade.executioner(command, command, 0, True)
|
|
|
|
# Ensure log directory exists for scheduled scans
|
|
if not os.path.exists('/usr/local/lscp/logs'):
|
|
try:
|
|
os.makedirs('/usr/local/lscp/logs', mode=0o755)
|
|
except:
|
|
pass
|
|
|
|
if os.path.exists('/usr/local/lsws/conf/httpd.conf'):
|
|
# Setup /usr/local/lsws/conf/httpd.conf to use new Logformat standard for better stats and accesslogs
|
|
command = """sed -i "s|^LogFormat.*|LogFormat '%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"' combined|g" /usr/local/lsws/conf/httpd.conf"""
|
|
Upgrade.executioner(command, command, 0, True)
|
|
|
|
# Fix all existing vhost confs to use new Logformat standard for better stats and accesslogs
|
|
command = """find /usr/local/lsws/conf/vhosts/ -type f -name 'vhost.conf' -exec sed -i "s/.*CustomLog.*/ LogFormat '%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"' combined\n&/g" {} \;"""
|
|
Upgrade.executioner(command, command, 0, True)
|
|
|
|
# Install any Cyberpanel missing crons to root crontab so its visible to users via crontab -l as root user
|
|
|
|
# Install findBWUsage cron if missing
|
|
|
|
CentOSPath = '/etc/redhat-release'
|
|
openEulerPath = '/etc/openEuler-release'
|
|
|
|
if os.path.exists(CentOSPath) or os.path.exists(openEulerPath):
|
|
cronPath = '/var/spool/cron/root'
|
|
else:
|
|
cronPath = '/var/spool/cron/crontabs/root'
|
|
|
|
if os.path.exists(cronPath):
|
|
data = open(cronPath, 'r').read()
|
|
|
|
if data.find('findBWUsage') == -1:
|
|
content = """
|
|
0 * * * * /usr/local/CyberCP/bin/python /usr/local/CyberCP/plogical/findBWUsage.py >/dev/null 2>&1
|
|
0 * * * * /usr/local/CyberCP/bin/python /usr/local/CyberCP/postfixSenderPolicy/client.py hourlyCleanup >/dev/null 2>&1
|
|
0 0 1 * * /usr/local/CyberCP/bin/python /usr/local/CyberCP/postfixSenderPolicy/client.py monthlyCleanup >/dev/null 2>&1
|
|
0 2 * * * /usr/local/CyberCP/bin/python /usr/local/CyberCP/plogical/upgradeCritical.py >/dev/null 2>&1
|
|
0 0 * * 4 /usr/local/CyberCP/bin/python /usr/local/CyberCP/plogical/renew.py >/dev/null 2>&1
|
|
7 0 * * * "/root/.acme.sh"/acme.sh --cron --home "/root/.acme.sh" > /dev/null
|
|
0 1 * * * /usr/local/CyberCP/bin/python /usr/local/CyberCP/manage.py ssl_reconcile --all >/dev/null 2>&1
|
|
*/3 * * * * if ! find /home/*/public_html/ -maxdepth 2 -type f -newer /usr/local/lsws/cgid -name '.htaccess' -exec false {} +; then /usr/local/lsws/bin/lswsctrl restart; fi
|
|
* * * * * /usr/local/CyberCP/bin/python /usr/local/CyberCP/manage.py run_scheduled_scans >/usr/local/lscp/logs/scheduled_scans.log 2>&1
|
|
"""
|
|
|
|
writeToFile = open(cronPath, 'w')
|
|
writeToFile.write(content)
|
|
writeToFile.close()
|
|
|
|
if data.find('IncScheduler.py') == -1:
|
|
content = """
|
|
0 12 * * * /usr/local/CyberCP/bin/python /usr/local/CyberCP/IncBackups/IncScheduler.py Daily
|
|
0 0 * * 0 /usr/local/CyberCP/bin/python /usr/local/CyberCP/IncBackups/IncScheduler.py Weekly
|
|
"""
|
|
writeToFile = open(cronPath, 'a')
|
|
writeToFile.write(content)
|
|
writeToFile.close()
|
|
|
|
if data.find("IncScheduler.py '30 Minutes'") == -1:
|
|
content = """
|
|
*/30 * * * * /usr/local/CyberCP/bin/python /usr/local/CyberCP/IncBackups/IncScheduler.py '30 Minutes'
|
|
0 * * * * /usr/local/CyberCP/bin/python /usr/local/CyberCP/IncBackups/IncScheduler.py '1 Hour'
|
|
0 */6 * * * /usr/local/CyberCP/bin/python /usr/local/CyberCP/IncBackups/IncScheduler.py '6 Hours'
|
|
0 */12 * * * /usr/local/CyberCP/bin/python /usr/local/CyberCP/IncBackups/IncScheduler.py '12 Hours'
|
|
0 1 * * * /usr/local/CyberCP/bin/python /usr/local/CyberCP/IncBackups/IncScheduler.py '1 Day'
|
|
0 0 */3 * * /usr/local/CyberCP/bin/python /usr/local/CyberCP/IncBackups/IncScheduler.py '3 Days'
|
|
0 0 * * 0 /usr/local/CyberCP/bin/python /usr/local/CyberCP/IncBackups/IncScheduler.py '1 Week'
|
|
"""
|
|
writeToFile = open(cronPath, 'a')
|
|
writeToFile.write(content)
|
|
writeToFile.close()
|
|
|
|
# Add AI Scanner scheduled scans cron job if missing
|
|
if data.find('run_scheduled_scans') == -1:
|
|
content = """
|
|
* * * * * /usr/local/CyberCP/bin/python /usr/local/CyberCP/manage.py run_scheduled_scans >/usr/local/lscp/logs/scheduled_scans.log 2>&1
|
|
"""
|
|
writeToFile = open(cronPath, 'a')
|
|
writeToFile.write(content)
|
|
writeToFile.close()
|
|
|
|
|
|
else:
|
|
content = """
|
|
0 * * * * /usr/local/CyberCP/bin/python /usr/local/CyberCP/plogical/findBWUsage.py >/dev/null 2>&1
|
|
0 * * * * /usr/local/CyberCP/bin/python /usr/local/CyberCP/postfixSenderPolicy/client.py hourlyCleanup >/dev/null 2>&1
|
|
0 0 1 * * /usr/local/CyberCP/bin/python /usr/local/CyberCP/postfixSenderPolicy/client.py monthlyCleanup >/dev/null 2>&1
|
|
0 2 * * * /usr/local/CyberCP/bin/python /usr/local/CyberCP/plogical/upgradeCritical.py >/dev/null 2>&1
|
|
0 0 * * 4 /usr/local/CyberCP/bin/python /usr/local/CyberCP/plogical/renew.py >/dev/null 2>&1
|
|
7 0 * * * "/root/.acme.sh"/acme.sh --cron --home "/root/.acme.sh" > /dev/null
|
|
0 1 * * * /usr/local/CyberCP/bin/python /usr/local/CyberCP/manage.py ssl_reconcile --all >/dev/null 2>&1
|
|
0 0 * * * /usr/local/CyberCP/bin/python /usr/local/CyberCP/IncBackups/IncScheduler.py Daily
|
|
0 0 * * 0 /usr/local/CyberCP/bin/python /usr/local/CyberCP/IncBackups/IncScheduler.py Weekly
|
|
* * * * * /usr/local/CyberCP/bin/python /usr/local/CyberCP/manage.py run_scheduled_scans >/usr/local/lscp/logs/scheduled_scans.log 2>&1
|
|
"""
|
|
writeToFile = open(cronPath, 'w')
|
|
writeToFile.write(content)
|
|
writeToFile.close()
|
|
|
|
### Check and remove OLS restart if lsws ent detected
|
|
|
|
if not os.path.exists('/usr/local/lsws/bin/openlitespeed'):
|
|
|
|
data = open(cronPath, 'r').readlines()
|
|
|
|
writeToFile = open(cronPath, 'w')
|
|
|
|
for items in data:
|
|
if items.find('-maxdepth 2 -type f -newer') > -1:
|
|
pass
|
|
else:
|
|
writeToFile.writelines(items)
|
|
|
|
writeToFile.close()
|
|
|
|
if not os.path.exists(CentOSPath) or not os.path.exists(openEulerPath):
|
|
command = 'chmod 600 %s' % (cronPath)
|
|
Upgrade.executioner(command, 0)
|
|
|
|
@staticmethod
|
|
def UpdateConfigOfCustomACL():
|
|
sys.path.append('/usr/local/CyberCP')
|
|
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "CyberCP.settings")
|
|
import django
|
|
django.setup()
|
|
from loginSystem.models import ACL
|
|
for acl in ACL.objects.all():
|
|
if acl.name == 'admin' or acl.name == 'reseller' or acl.name == 'user':
|
|
continue
|
|
elif acl.config == '{}':
|
|
acl.config = '{"adminStatus":%s, "versionManagement": %s, "createNewUser": %s, "listUsers": %s, "deleteUser": %s, "resellerCenter": %s, "changeUserACL": %s, "createWebsite": %s, "modifyWebsite": %s, "suspendWebsite": %s, "deleteWebsite": %s, "createPackage": %s, "listPackages": %s, "deletePackage": %s, "modifyPackage": %s, "createDatabase": %s, "deleteDatabase": %s, "listDatabases": %s, "createNameServer": %s, "createDNSZone": %s, "deleteZone": %s, "addDeleteRecords": %s, "createEmail": %s, "listEmails": %s, "deleteEmail": %s, "emailForwarding": %s, "changeEmailPassword": %s, "dkimManager": %s, "createFTPAccount": %s, "deleteFTPAccount": %s, "listFTPAccounts": %s, "createBackup": %s, "restoreBackup": %s, "addDeleteDestinations": %s, "scheduleBackups": %s, "remoteBackups": %s, "googleDriveBackups": %s, "manageSSL": %s, "hostnameSSL": %s, "mailServerSSL": %s }' \
|
|
% (str(acl.adminStatus), str(acl.versionManagement), str(acl.createNewUser),
|
|
str(acl.listUsers), str(acl.deleteUser), str(acl.resellerCenter),
|
|
str(acl.changeUserACL),
|
|
str(acl.createWebsite), str(acl.modifyWebsite), str(acl.suspendWebsite),
|
|
str(acl.deleteWebsite),
|
|
str(acl.createPackage), str(acl.listPackages), str(acl.deletePackage),
|
|
str(acl.modifyPackage),
|
|
str(acl.createDatabase), str(acl.deleteDatabase), str(acl.listDatabases),
|
|
str(acl.createNameServer),
|
|
str(acl.createDNSZone), str(acl.deleteZone), str(acl.addDeleteRecords),
|
|
str(acl.createEmail),
|
|
str(acl.listEmails), str(acl.deleteEmail), str(acl.emailForwarding),
|
|
str(acl.changeEmailPassword),
|
|
str(acl.dkimManager), str(acl.createFTPAccount), str(acl.deleteFTPAccount),
|
|
str(acl.listFTPAccounts),
|
|
str(acl.createBackup), str(acl.restoreBackup), str(acl.addDeleteDestinations),
|
|
str(acl.scheduleBackups), str(acl.remoteBackups), '1',
|
|
str(acl.manageSSL), str(acl.hostnameSSL), str(acl.mailServerSSL))
|
|
acl.save()
|
|
|
|
@staticmethod
|
|
def CreateMissingPoolsforFPM():
|
|
"""
|
|
Create missing PHP-FPM pool configurations for all PHP versions.
|
|
This function ensures all PHP versions have proper pool configurations
|
|
to prevent ImunifyAV/Imunify360 installation failures.
|
|
"""
|
|
try:
|
|
# Detect OS and set paths
|
|
CentOSPath = '/etc/redhat-release'
|
|
|
|
if os.path.exists(CentOSPath):
|
|
# CentOS/RHEL/CloudLinux paths
|
|
serverRootPath = '/etc/httpd'
|
|
configBasePath = '/etc/httpd/conf.d/'
|
|
sockPath = '/var/run/php-fpm/'
|
|
runAsUser = 'apache'
|
|
group = 'nobody'
|
|
|
|
# Define PHP pool paths for CentOS
|
|
php_paths = {
|
|
'5.4': '/opt/remi/php54/root/etc/php-fpm.d/',
|
|
'5.5': '/opt/remi/php55/root/etc/php-fpm.d/',
|
|
'5.6': '/etc/opt/remi/php56/php-fpm.d/',
|
|
'7.0': '/etc/opt/remi/php70/php-fpm.d/',
|
|
'7.1': '/etc/opt/remi/php71/php-fpm.d/',
|
|
'7.2': '/etc/opt/remi/php72/php-fpm.d/',
|
|
'7.3': '/etc/opt/remi/php73/php-fpm.d/',
|
|
'7.4': '/etc/opt/remi/php74/php-fpm.d/',
|
|
'8.0': '/etc/opt/remi/php80/php-fpm.d/',
|
|
'8.1': '/etc/opt/remi/php81/php-fpm.d/',
|
|
'8.2': '/etc/opt/remi/php82/php-fpm.d/',
|
|
'8.3': '/etc/opt/remi/php83/php-fpm.d/',
|
|
'8.4': '/etc/opt/remi/php84/php-fpm.d/',
|
|
'8.5': '/etc/opt/remi/php85/php-fpm.d/'
|
|
}
|
|
else:
|
|
# Ubuntu/Debian paths
|
|
serverRootPath = '/etc/apache2'
|
|
configBasePath = '/etc/apache2/sites-enabled/'
|
|
sockPath = '/var/run/php/'
|
|
runAsUser = 'www-data'
|
|
group = 'nogroup'
|
|
|
|
# Define PHP pool paths for Ubuntu
|
|
php_paths = {
|
|
'5.4': '/etc/php/5.4/fpm/pool.d/',
|
|
'5.5': '/etc/php/5.5/fpm/pool.d/',
|
|
'5.6': '/etc/php/5.6/fpm/pool.d/',
|
|
'7.0': '/etc/php/7.0/fpm/pool.d/',
|
|
'7.1': '/etc/php/7.1/fpm/pool.d/',
|
|
'7.2': '/etc/php/7.2/fpm/pool.d/',
|
|
'7.3': '/etc/php/7.3/fpm/pool.d/',
|
|
'7.4': '/etc/php/7.4/fpm/pool.d/',
|
|
'8.0': '/etc/php/8.0/fpm/pool.d/',
|
|
'8.1': '/etc/php/8.1/fpm/pool.d/',
|
|
'8.2': '/etc/php/8.2/fpm/pool.d/',
|
|
'8.3': '/etc/php/8.3/fpm/pool.d/',
|
|
'8.4': '/etc/php/8.4/fpm/pool.d/',
|
|
'8.5': '/etc/php/8.5/fpm/pool.d/'
|
|
}
|
|
|
|
# Check if server root exists
|
|
if not os.path.exists(serverRootPath):
|
|
logging.CyberCPLogFileWriter.writeToFile(f'Server root path not found: {serverRootPath}')
|
|
return 1
|
|
|
|
# Create pool configurations for all PHP versions
|
|
for version, pool_path in php_paths.items():
|
|
if os.path.exists(pool_path):
|
|
www_conf = os.path.join(pool_path, 'www.conf')
|
|
|
|
# Skip if www.conf already exists
|
|
if os.path.exists(www_conf):
|
|
logging.CyberCPLogFileWriter.writeToFile(f'PHP {version} pool config already exists: {www_conf}')
|
|
continue
|
|
|
|
# Create the pool configuration
|
|
pool_name = f'php{version.replace(".", "")}default'
|
|
sock_name = f'php{version}-fpm.sock'
|
|
|
|
content = f'''[{pool_name}]
|
|
user = {runAsUser}
|
|
group = {runAsUser}
|
|
listen = {sockPath}{sock_name}
|
|
listen.owner = {runAsUser}
|
|
listen.group = {group}
|
|
listen.mode = 0660
|
|
pm = dynamic
|
|
pm.max_children = 5
|
|
pm.start_servers = 2
|
|
pm.min_spare_servers = 1
|
|
pm.max_spare_servers = 3
|
|
pm.max_requests = 1000
|
|
pm.status_path = /status
|
|
ping.path = /ping
|
|
ping.response = pong
|
|
request_terminate_timeout = 300
|
|
request_slowlog_timeout = 10
|
|
slowlog = /var/log/php{version}-fpm-slow.log
|
|
'''
|
|
|
|
try:
|
|
# Write the configuration file
|
|
with open(www_conf, 'w') as f:
|
|
f.write(content)
|
|
|
|
# Set proper permissions
|
|
os.chown(www_conf, 0, 0) # root:root
|
|
os.chmod(www_conf, 0o644)
|
|
|
|
logging.CyberCPLogFileWriter.writeToFile(f'Created PHP {version} pool config: {www_conf}')
|
|
|
|
except Exception as e:
|
|
logging.CyberCPLogFileWriter.writeToFile(f'Error creating PHP {version} pool config: {str(e)}')
|
|
else:
|
|
logging.CyberCPLogFileWriter.writeToFile(f'PHP {version} pool directory not found: {pool_path}')
|
|
|
|
# Restart PHP-FPM services to apply configurations
|
|
Upgrade.restartPHPFPMServices()
|
|
|
|
return 0
|
|
|
|
except Exception as e:
|
|
logging.CyberCPLogFileWriter.writeToFile(f'Error in CreateMissingPoolsforFPM: {str(e)}')
|
|
return 1
|
|
|
|
@staticmethod
|
|
def restartPHPFPMServices():
|
|
"""
|
|
Restart all PHP-FPM services to apply new pool configurations.
|
|
This ensures that ImunifyAV/Imunify360 installation will work properly.
|
|
"""
|
|
try:
|
|
# Define all possible PHP versions
|
|
php_versions = ['5.4', '5.5', '5.6', '7.0', '7.1', '7.2', '7.3', '7.4', '8.0', '8.1', '8.2', '8.3', '8.4', '8.5']
|
|
|
|
restarted_count = 0
|
|
total_count = 0
|
|
|
|
for version in php_versions:
|
|
service_name = f'php{version}-fpm'
|
|
|
|
# Check if service exists
|
|
try:
|
|
result = subprocess.run(['systemctl', 'list-unit-files', service_name],
|
|
capture_output=True, text=True, timeout=10)
|
|
if result.returncode == 0 and service_name in result.stdout:
|
|
total_count += 1
|
|
|
|
# Restart the service
|
|
restart_result = subprocess.run(['systemctl', 'restart', service_name],
|
|
capture_output=True, text=True, timeout=30)
|
|
|
|
if restart_result.returncode == 0:
|
|
# Check if service is actually running
|
|
status_result = subprocess.run(['systemctl', 'is-active', service_name],
|
|
capture_output=True, text=True, timeout=10)
|
|
if status_result.returncode == 0 and 'active' in status_result.stdout:
|
|
restarted_count += 1
|
|
logging.CyberCPLogFileWriter.writeToFile(f'Successfully restarted {service_name}')
|
|
else:
|
|
logging.CyberCPLogFileWriter.writeToFile(f'Warning: {service_name} restarted but not active')
|
|
else:
|
|
logging.CyberCPLogFileWriter.writeToFile(f'Failed to restart {service_name}: {restart_result.stderr}')
|
|
|
|
except subprocess.TimeoutExpired:
|
|
logging.CyberCPLogFileWriter.writeToFile(f'Timeout restarting {service_name}')
|
|
except Exception as e:
|
|
logging.CyberCPLogFileWriter.writeToFile(f'Error restarting {service_name}: {str(e)}')
|
|
|
|
logging.CyberCPLogFileWriter.writeToFile(f'PHP-FPM restart summary: {restarted_count}/{total_count} services restarted successfully')
|
|
return restarted_count, total_count
|
|
|
|
except Exception as e:
|
|
logging.CyberCPLogFileWriter.writeToFile(f'Error in restartPHPFPMServices: {str(e)}')
|
|
return 0, 0
|
|
|
|
@staticmethod
|
|
def setupPHPSymlink():
|
|
try:
|
|
# Try to find available PHP version (prioritize modern stable versions)
|
|
# Priority: 8.3 (recommended), 8.2, 8.4, 8.5, 8.1, 8.0, then older versions
|
|
php_versions = ['83', '82', '84', '85', '81', '80', '74', '73', '72', '71']
|
|
selected_php = None
|
|
|
|
for version in php_versions:
|
|
if os.path.exists(f'/usr/local/lsws/lsphp{version}/bin/php'):
|
|
selected_php = version
|
|
Upgrade.stdOut(f"Found PHP {version}, using as default", 1)
|
|
break
|
|
|
|
if not selected_php:
|
|
# Try to install PHP 8.3 as fallback (modern stable version)
|
|
Upgrade.stdOut("No PHP found, installing PHP 8.3 as fallback...")
|
|
|
|
# Install PHP 8.3 based on OS
|
|
if os.path.exists(Upgrade.CentOSPath) or os.path.exists(Upgrade.openEulerPath):
|
|
command = 'yum install lsphp83 lsphp83-* -y'
|
|
Upgrade.executioner(command, 'Install PHP 8.3', 0)
|
|
else:
|
|
command = 'DEBIAN_FRONTEND=noninteractive apt-get update && DEBIAN_FRONTEND=noninteractive apt-get -y install lsphp83 lsphp83-*'
|
|
Upgrade.executioner(command, 'Install PHP 8.3', 0)
|
|
|
|
# Verify installation
|
|
if not os.path.exists('/usr/local/lsws/lsphp83/bin/php'):
|
|
Upgrade.stdOut('[ERROR] Failed to install PHP 8.3')
|
|
return 0
|
|
selected_php = '83'
|
|
|
|
# Remove existing PHP symlink if it exists
|
|
if os.path.exists('/usr/bin/php'):
|
|
os.remove('/usr/bin/php')
|
|
|
|
# Create symlink to selected PHP version
|
|
command = f'ln -s /usr/local/lsws/lsphp{selected_php}/bin/php /usr/bin/php'
|
|
Upgrade.executioner(command, f'Setup PHP Symlink to {selected_php}', 0)
|
|
|
|
Upgrade.stdOut(f"PHP symlink updated to PHP {selected_php} successfully.")
|
|
|
|
except Exception as e:
|
|
ErrorSanitizer.log_error_securely(e, 'setupPHPSymlink')
|
|
Upgrade.stdOut('[ERROR] Failed to setup PHP symlink [setupPHPSymlink]')
|
|
return 0
|
|
|
|
return 1
|
|
|
|
@staticmethod
|
|
def upgrade(branch):
|
|
|
|
if branch.find('SoftUpgrade') > -1:
|
|
Upgrade.SoftUpgrade = 1
|
|
branch = branch.split(',')[1]
|
|
|
|
# Upgrade.stdOut("Upgrades are currently disabled")
|
|
# return 0
|
|
|
|
if os.path.exists(Upgrade.CentOSPath) or os.path.exists(Upgrade.openEulerPath):
|
|
command = 'yum list installed'
|
|
try:
|
|
Upgrade.installedOutput = subprocess.check_output(shlex.split(command)).decode()
|
|
except Exception as e:
|
|
Upgrade.stdOut(f"Error getting installed packages: {str(e)}")
|
|
Upgrade.installedOutput = ""
|
|
else:
|
|
command = 'apt list'
|
|
try:
|
|
Upgrade.installedOutput = subprocess.check_output(shlex.split(command)).decode()
|
|
except Exception as e:
|
|
Upgrade.stdOut(f"Error getting installed packages: {str(e)}")
|
|
Upgrade.installedOutput = ""
|
|
|
|
# command = 'systemctl stop cpssh'
|
|
# Upgrade.executioner(command, 'fix csf if there', 0)
|
|
|
|
## Add LSPHP7.4 TO LSWS Ent configs
|
|
|
|
if not os.path.exists('/usr/local/lsws/bin/openlitespeed'):
|
|
|
|
if os.path.exists('httpd_config.xml'):
|
|
os.remove('httpd_config.xml')
|
|
|
|
command = 'wget https://raw.githubusercontent.com/usmannasir/cyberpanel/stable/install/litespeed/httpd_config.xml'
|
|
Upgrade.executioner(command, command, 0)
|
|
# os.remove('/usr/local/lsws/conf/httpd_config.xml')
|
|
# shutil.copy('httpd_config.xml', '/usr/local/lsws/conf/httpd_config.xml')
|
|
|
|
Upgrade.updateRepoURL()
|
|
|
|
os.chdir("/usr/local")
|
|
|
|
if os.path.exists(Upgrade.CentOSPath) or os.path.exists(Upgrade.openEulerPath):
|
|
command = 'yum remove yum-plugin-priorities -y'
|
|
Upgrade.executioner(command, 'remove yum-plugin-priorities', 0)
|
|
|
|
## Current Version
|
|
|
|
### if this is a soft upgrade from front end do not stop lscpd, as lscpd is controlling the front end
|
|
|
|
if Upgrade.SoftUpgrade == 0:
|
|
command = "systemctl stop lscpd"
|
|
Upgrade.executioner(command, 'stop lscpd', 0)
|
|
|
|
Upgrade.fixSudoers()
|
|
# Upgrade.mountTemp()
|
|
|
|
### fix a temp issue causing upgrade problem
|
|
|
|
fstab = "/etc/fstab"
|
|
|
|
if open(fstab, 'r').read().find('/usr/.tempdisk')>-1:
|
|
command = 'umount -l /tmp'
|
|
Upgrade.executioner(command, 'tmp adjustment', 0)
|
|
|
|
command = 'mount -t tmpfs -o size=2G tmpfs /tmp'
|
|
Upgrade.executioner(command, 'tmp adjustment', 0)
|
|
|
|
Upgrade.dockerUsers()
|
|
Upgrade.setupPHPSymlink()
|
|
Upgrade.setupComposer()
|
|
|
|
# Install custom OpenLiteSpeed binaries if OLS is installed
|
|
if os.path.exists('/usr/local/lsws/bin/openlitespeed'):
|
|
Upgrade.installCustomOLSBinaries()
|
|
|
|
##
|
|
|
|
versionNumbring = Upgrade.downloadLink()
|
|
|
|
if os.path.exists('/usr/local/CyberPanel.' + versionNumbring):
|
|
os.remove('/usr/local/CyberPanel.' + versionNumbring)
|
|
|
|
##
|
|
|
|
# execPath = "sudo /usr/local/CyberCP/bin/python /usr/local/CyberCP/plogical/csf.py"
|
|
# execPath = execPath + " removeCSF"
|
|
# Upgrade.executioner(execPath, 'fix csf if there', 0)
|
|
|
|
Upgrade.downloadAndUpgrade(versionNumbring, branch)
|
|
versionNumbring = Upgrade.downloadLink()
|
|
Upgrade.download_install_phpmyadmin()
|
|
Upgrade.downoad_and_install_raindloop()
|
|
|
|
##
|
|
|
|
##
|
|
|
|
Upgrade.mailServerMigrations()
|
|
Upgrade.emailMarketingMigrationsa()
|
|
Upgrade.dockerMigrations()
|
|
Upgrade.CLMigrations()
|
|
Upgrade.IncBackupMigrations()
|
|
Upgrade.installRestic()
|
|
|
|
##
|
|
|
|
# Upgrade.setupVirtualEnv()
|
|
|
|
##
|
|
|
|
Upgrade.applyLoginSystemMigrations()
|
|
|
|
## Put function here to update custom ACLs
|
|
|
|
Upgrade.UpdateConfigOfCustomACL()
|
|
|
|
Upgrade.s3BackupMigrations()
|
|
Upgrade.containerMigrations()
|
|
Upgrade.manageServiceMigrations()
|
|
Upgrade.enableServices()
|
|
|
|
# Apply AlmaLinux 9 fixes before other installations
|
|
Upgrade.fix_almalinux9_mariadb()
|
|
|
|
Upgrade.installPHP73()
|
|
Upgrade.setupCLI()
|
|
Upgrade.someDirectories()
|
|
Upgrade.installLSCPD(branch)
|
|
Upgrade.FixCurrentQuoatasSystem()
|
|
|
|
## Fix Apache configuration issues after upgrade
|
|
Upgrade.fixApacheConfiguration()
|
|
|
|
# Fix LiteSpeed configuration files if missing
|
|
Upgrade.fixLiteSpeedConfig()
|
|
|
|
# Fix comprehensive service configuration issues (503 error prevention)
|
|
Upgrade.fixServiceConfiguration()
|
|
|
|
# Fix subdomain log configurations
|
|
Upgrade.fixSubdomainLogConfigurations()
|
|
|
|
### General migrations are not needed any more
|
|
|
|
# Upgrade.GeneralMigrations()
|
|
|
|
# Fix baseTemplate migrations for AlmaLinux 9 and Ubuntu 24 compatibility
|
|
Upgrade.fixBaseTemplateMigrations()
|
|
|
|
# Upgrade.p3()
|
|
|
|
## Also disable email service upgrade
|
|
|
|
# if os.path.exists(postfixPath):
|
|
# Upgrade.upgradeDovecot()
|
|
|
|
## Upgrade version
|
|
|
|
Upgrade.fixPermissions()
|
|
|
|
##
|
|
|
|
### Disable version upgrade too
|
|
|
|
# Upgrade.upgradeVersion()
|
|
|
|
Upgrade.UpdateMaxSSLCons()
|
|
|
|
## Update LSCPD PHP
|
|
|
|
phpPath = '/usr/local/lscp/fcgi-bin/lsphp'
|
|
|
|
try:
|
|
os.remove(phpPath)
|
|
except:
|
|
pass
|
|
|
|
# Try to find available PHP binary in order of preference (modern stable first)
|
|
php_versions = ['83', '82', '84', '85', '81', '80', '74', '73', '72', '71']
|
|
php_binary_found = False
|
|
|
|
for version in php_versions:
|
|
php_binary = f'/usr/local/lsws/lsphp{version}/bin/lsphp'
|
|
if os.path.exists(php_binary):
|
|
command = f'cp {php_binary} {phpPath}'
|
|
Upgrade.executioner(command, 0)
|
|
Upgrade.stdOut(f"Using PHP {version} for LSCPD", 1)
|
|
php_binary_found = True
|
|
break
|
|
|
|
if not php_binary_found:
|
|
Upgrade.stdOut("Warning: No PHP binary found for LSCPD", 0)
|
|
# Try to create a symlink to any available PHP
|
|
try:
|
|
command = 'find /usr/local/lsws -name "lsphp" -type f 2>/dev/null | head -1'
|
|
result = subprocess.run(command, shell=True, capture_output=True, text=True)
|
|
if result.stdout.strip():
|
|
php_binary = result.stdout.strip()
|
|
command = f'cp {php_binary} {phpPath}'
|
|
Upgrade.executioner(command, 0)
|
|
Upgrade.stdOut(f"Using found PHP binary: {php_binary}", 1)
|
|
except:
|
|
pass
|
|
|
|
if Upgrade.SoftUpgrade == 0:
|
|
try:
|
|
command = "systemctl start lscpd"
|
|
Upgrade.executioner(command, 'Start LSCPD', 0)
|
|
except:
|
|
pass
|
|
|
|
# Try to start other services if they exist
|
|
# Enhanced service startup with AlmaLinux 9 support
|
|
services_to_start = ['fastapi_ssh_server', 'cyberpanel']
|
|
|
|
# Special handling for AlmaLinux 9 MariaDB service
|
|
if Upgrade.is_almalinux9():
|
|
Upgrade.stdOut("AlmaLinux 9 detected - applying enhanced service management", 1)
|
|
mariadb_services = ['mariadb', 'mysql', 'mysqld']
|
|
for service in mariadb_services:
|
|
try:
|
|
check_command = f"systemctl list-unit-files | grep -q {service}"
|
|
result = subprocess.run(check_command, shell=True, capture_output=True)
|
|
if result.returncode == 0:
|
|
command = f"systemctl restart {service}"
|
|
Upgrade.executioner(command, f'Restart {service} for AlmaLinux 9', 0)
|
|
command = f"systemctl enable {service}"
|
|
Upgrade.executioner(command, f'Enable {service} for AlmaLinux 9', 0)
|
|
Upgrade.stdOut(f"MariaDB service managed as {service} on AlmaLinux 9", 1)
|
|
break
|
|
except Exception as e:
|
|
Upgrade.stdOut(f"Could not manage MariaDB service {service}: {str(e)}", 0)
|
|
continue
|
|
|
|
for service in services_to_start:
|
|
try:
|
|
# Check if service exists
|
|
check_command = f"systemctl list-unit-files | grep -q {service}"
|
|
result = subprocess.run(check_command, shell=True, capture_output=True)
|
|
if result.returncode == 0:
|
|
command = f"systemctl start {service}"
|
|
Upgrade.executioner(command, f'Start {service}', 0)
|
|
else:
|
|
Upgrade.stdOut(f"Service {service} not found, skipping", 0)
|
|
except Exception as e:
|
|
Upgrade.stdOut(f"Could not start {service}: {str(e)}", 0)
|
|
|
|
# Remove CSF if installed and restore firewalld (CSF is being discontinued on August 31, 2025)
|
|
if os.path.exists('/etc/csf'):
|
|
print("CSF detected - removing CSF and restoring firewalld...")
|
|
print("Note: ConfigServer Firewall (CSF) is being discontinued on August 31, 2025")
|
|
|
|
# Remove CSF and restore firewalld
|
|
execPath = "sudo /usr/local/CyberCP/bin/python /usr/local/CyberCP/plogical/csf.py"
|
|
execPath = execPath + " removeCSF"
|
|
Upgrade.executioner(execPath, 'Remove CSF and restore firewalld', 0)
|
|
|
|
print("CSF has been removed and firewalld has been restored.")
|
|
|
|
|
|
|
|
# Remove configservercsf directory if it exists
|
|
if os.path.exists('/usr/local/CyberCP/configservercsf'):
|
|
command = 'rm -rf /usr/local/CyberCP/configservercsf'
|
|
Upgrade.executioner(command, 'Remove configservercsf directory', 1)
|
|
|
|
|
|
|
|
command = 'systemctl stop cpssh'
|
|
Upgrade.executioner(command, 'fix csf if there', 0)
|
|
Upgrade.AutoUpgradeAcme()
|
|
Upgrade.installCLScripts()
|
|
Upgrade.runSomeImportantBash()
|
|
Upgrade.FixRSPAMDConfig()
|
|
Upgrade.CreateMissingPoolsforFPM()
|
|
|
|
# ## Handle ImunifyAV and Imunify360 separately
|
|
|
|
# Both products use the same config file, so we need to read its content to determine which product
|
|
integrationConfig = '/etc/sysconfig/imunify360/integration.conf'
|
|
|
|
if os.path.exists(integrationConfig):
|
|
try:
|
|
with open(integrationConfig, 'r') as f:
|
|
configContent = f.read()
|
|
|
|
# Check which product the config file is for by looking at the ui_path
|
|
if 'ui_path =/usr/local/CyberCP/public/imunifyav' in configContent:
|
|
# This is ImunifyAV configuration
|
|
Upgrade.stdOut("Detected ImunifyAV configuration, reconfiguring...")
|
|
imunifyAVPath = '/usr/local/CyberCP/public/imunifyav'
|
|
|
|
if os.path.exists(imunifyAVPath):
|
|
execPath = "/usr/local/CyberCP/bin/python /usr/local/CyberCP/CLManager/CageFS.py"
|
|
command = execPath + " --function submitinstallImunifyAV"
|
|
Upgrade.executioner(command, command, 1)
|
|
|
|
# Set permissions on ImunifyAV execute file
|
|
imunifyAVExecute = '/usr/local/CyberCP/public/imunifyav/bin/execute.py'
|
|
if os.path.exists(imunifyAVExecute):
|
|
command = 'chmod +x ' + imunifyAVExecute
|
|
Upgrade.executioner(command, command, 1)
|
|
Upgrade.stdOut("ImunifyAV execute permissions set")
|
|
else:
|
|
Upgrade.stdOut("ImunifyAV execute.py file not found")
|
|
else:
|
|
Upgrade.stdOut("ImunifyAV directory not found despite config file existing")
|
|
|
|
elif 'ui_path =/usr/local/CyberCP/public/imunify' in configContent:
|
|
# This is Imunify360 configuration
|
|
Upgrade.stdOut("Detected Imunify360 configuration, checking system installation...")
|
|
imunify360Path = '/usr/local/CyberCP/public/imunify'
|
|
|
|
if os.path.exists(imunify360Path):
|
|
# Check if Imunify360 is actually installed on the system
|
|
imunify360Installed = False
|
|
if os.path.exists('/usr/bin/imunify360-agent') or os.path.exists('/opt/imunify360'):
|
|
imunify360Installed = True
|
|
Upgrade.stdOut("Imunify360 system installation detected")
|
|
|
|
if imunify360Installed:
|
|
Upgrade.stdOut("Imunify360 directory found and system is installed, ensuring proper integration...")
|
|
# Reinstall Imunify360 firewall to ensure integration
|
|
command = "yum reinstall imunify360-firewall-generic -y" if os.path.exists(Upgrade.CentOSPath) else "apt install --reinstall imunify360-firewall-generic -y"
|
|
Upgrade.executioner(command, command, 1)
|
|
else:
|
|
Upgrade.stdOut("Imunify360 directory found but system not installed - manual installation may be needed")
|
|
|
|
# Set permissions on Imunify360 execute file
|
|
imunify360Execute = '/usr/local/CyberCP/public/imunify/bin/execute.py'
|
|
if os.path.exists(imunify360Execute):
|
|
command = f'chmod +x {imunify360Execute}'
|
|
Upgrade.executioner(command, f'Setting execute permissions on Imunify360 file', 0)
|
|
Upgrade.stdOut("Imunify360 execute permissions set")
|
|
else:
|
|
Upgrade.stdOut("Imunify360 execute.py file not found")
|
|
else:
|
|
Upgrade.stdOut("Imunify360 directory not found despite config file existing")
|
|
|
|
else:
|
|
Upgrade.stdOut(f"Unknown product in integration config file. Config content: {configContent[:200]}...")
|
|
|
|
except Exception as e:
|
|
Upgrade.stdOut(f"Error reading integration config file: {str(e)}")
|
|
else:
|
|
Upgrade.stdOut("No Imunify integration config file found")
|
|
|
|
@staticmethod
|
|
def restoreImunify360():
|
|
"""Restore and reconfigure Imunify360 after upgrade"""
|
|
try:
|
|
Upgrade.stdOut("=== STARTING IMUNIFY360 RESTORATION ===")
|
|
Upgrade.stdOut("Checking for Imunify360 restoration...")
|
|
|
|
# Check if Imunify360 directories were restored
|
|
imunifyPath = '/usr/local/CyberCP/public/imunify'
|
|
imunifyAVPath = '/usr/local/CyberCP/public/imunifyav'
|
|
configPath = '/etc/sysconfig/imunify360/integration.conf'
|
|
|
|
Upgrade.stdOut(f"Checking if Imunify360 path exists: {imunifyPath}")
|
|
Upgrade.stdOut(f"Path exists: {os.path.exists(imunifyPath)}")
|
|
|
|
restored = False
|
|
|
|
# Handle main Imunify360 firewall
|
|
if os.path.exists(imunifyPath):
|
|
Upgrade.stdOut("Imunify360 directory found, checking if reinstallation is needed...")
|
|
# Check if Imunify360 is actually installed on the system
|
|
if os.path.exists('/usr/bin/imunify360-agent') or os.path.exists('/opt/imunify360'):
|
|
Upgrade.stdOut("Imunify360 appears to be installed on system, ensuring proper integration...")
|
|
# Reinstall to ensure proper integration
|
|
command = "yum reinstall imunify360-firewall-generic -y" if os.path.exists(Upgrade.CentOSPath) else "apt install --reinstall imunify360-firewall-generic -y"
|
|
if Upgrade.executioner(command, command, 1):
|
|
Upgrade.stdOut("Imunify360 firewall reinstalled successfully")
|
|
restored = True
|
|
else:
|
|
Upgrade.stdOut("Warning: Failed to reinstall Imunify360 firewall")
|
|
else:
|
|
Upgrade.stdOut("Imunify360 not found on system, skipping firewall reinstallation")
|
|
|
|
# Handle ImunifyAV
|
|
if os.path.exists(imunifyAVPath):
|
|
Upgrade.stdOut("ImunifyAV directory found, reconfiguring...")
|
|
if os.path.exists(configPath):
|
|
execPath = "/usr/local/CyberCP/bin/python /usr/local/CyberCP/CLManager/CageFS.py"
|
|
command = execPath + " --function submitinstallImunifyAV"
|
|
if Upgrade.executioner(command, command, 1):
|
|
Upgrade.stdOut("ImunifyAV reconfigured successfully")
|
|
restored = True
|
|
|
|
# Ensure execute permissions
|
|
executePath = '/usr/local/CyberCP/public/imunifyav/bin/execute.py'
|
|
if os.path.exists(executePath):
|
|
command = f'chmod +x {executePath}'
|
|
Upgrade.executioner(command, command, 1)
|
|
|
|
# Handle main Imunify execute permissions - comprehensive solution for missing files
|
|
if os.path.exists(imunifyPath):
|
|
# First, check if the bin directory and execute.py file exist
|
|
binDir = '/usr/local/CyberCP/public/imunify/bin'
|
|
executeFile = '/usr/local/CyberCP/public/imunify/bin/execute.py'
|
|
|
|
if not os.path.exists(binDir):
|
|
Upgrade.stdOut(f"Warning: Imunify360 bin directory missing at {binDir}")
|
|
# Try to find if execute.py exists elsewhere
|
|
findCommand = f'find {imunifyPath} -name "execute.py" -type f 2>/dev/null'
|
|
Upgrade.stdOut(f"Searching for execute.py files with command: {findCommand}")
|
|
findResult = subprocess.getstatusoutput(findCommand)
|
|
Upgrade.stdOut(f"Find command result: exit_code={findResult[0]}, output='{findResult[1]}'")
|
|
|
|
if findResult[0] == 0 and findResult[1].strip():
|
|
Upgrade.stdOut(f"Found execute.py files: {findResult[1]}")
|
|
# Set permissions on all found execute.py files
|
|
command = f'find {imunifyPath} -name "execute.py" -type f -exec chmod +x {{}} \\; 2>/dev/null || true'
|
|
Upgrade.executioner(command, 'Setting execute permissions on found execute.py files', 0)
|
|
else:
|
|
Upgrade.stdOut("No execute.py files found in Imunify360 directory - installation may be incomplete")
|
|
else:
|
|
# Bin directory exists, try the direct approach
|
|
Upgrade.stdOut(f"Bin directory exists at {binDir}, attempting to set execute permissions")
|
|
Upgrade.stdOut(f"Checking if execute.py exists: {executeFile}")
|
|
Upgrade.stdOut(f"File exists: {os.path.exists(executeFile)}")
|
|
|
|
# Try direct chmod command first
|
|
if os.path.exists(executeFile):
|
|
Upgrade.stdOut("File exists, trying direct chmod command")
|
|
command = f'chmod +x {executeFile}'
|
|
Upgrade.stdOut(f"Executing direct command: {command}")
|
|
directResult = Upgrade.executioner(command, f'Direct chmod on {executeFile}', 0)
|
|
Upgrade.stdOut(f"Direct command result: {directResult}")
|
|
|
|
if directResult:
|
|
Upgrade.stdOut("SUCCESS: Direct chmod worked!")
|
|
restored = True
|
|
else:
|
|
Upgrade.stdOut("FAILED: Direct chmod failed, trying alternative")
|
|
|
|
# Try the community method as fallback
|
|
command = f'cd {imunifyPath} && chmod +x ./bin/execute.py 2>/dev/null || true'
|
|
Upgrade.stdOut(f"Trying community method: {command}")
|
|
communityResult = Upgrade.executioner(command, 'Community method chmod', 0)
|
|
Upgrade.stdOut(f"Community method result: {communityResult}")
|
|
|
|
if communityResult:
|
|
Upgrade.stdOut("SUCCESS: Community method worked!")
|
|
restored = True
|
|
else:
|
|
Upgrade.stdOut("FAILED: Both methods failed")
|
|
else:
|
|
Upgrade.stdOut(f"ERROR: execute.py file not found at {executeFile}")
|
|
|
|
# Try find method as final fallback
|
|
Upgrade.stdOut("Trying find method as final fallback")
|
|
command = f'find {imunifyPath} -name "execute.py" -type f -exec chmod +x {{}} \\; 2>/dev/null || true'
|
|
Upgrade.stdOut(f"Find command: {command}")
|
|
findResult = Upgrade.executioner(command, 'Find method chmod', 0)
|
|
Upgrade.stdOut(f"Find result: {findResult}")
|
|
|
|
if findResult and not restored:
|
|
Upgrade.stdOut("SUCCESS: Find method worked!")
|
|
restored = True
|
|
|
|
restored = True # Mark as restored even if files are missing, to indicate we processed it
|
|
|
|
if restored:
|
|
Upgrade.stdOut("Imunify360 restoration completed successfully")
|
|
else:
|
|
Upgrade.stdOut("No Imunify360 components found to restore")
|
|
|
|
except Exception as e:
|
|
Upgrade.stdOut(f"Error during Imunify360 restoration: {str(e)}")
|
|
|
|
@staticmethod
|
|
def finalImunifyPermissions():
|
|
"""FINAL STEP: Ensure Imunify360 execute permissions are set after everything else is complete"""
|
|
try:
|
|
Upgrade.stdOut("=== FINAL STEP: Setting Imunify360 Execute Permissions ===")
|
|
|
|
executeFile = '/usr/local/CyberCP/public/imunify/bin/execute.py'
|
|
|
|
if os.path.exists(executeFile):
|
|
Upgrade.stdOut(f"Setting execute permissions on: {executeFile}")
|
|
# Use the simplest, most reliable command
|
|
command = f'chmod +x {executeFile}'
|
|
result = Upgrade.executioner(command, f'Final chmod +x on {executeFile}', 0)
|
|
|
|
if result:
|
|
Upgrade.stdOut("✅ SUCCESS: Imunify360 execute permissions set successfully!")
|
|
else:
|
|
Upgrade.stdOut("❌ FAILED: Could not set Imunify360 execute permissions")
|
|
|
|
# Verify the permissions were set
|
|
try:
|
|
import stat
|
|
file_stat = os.stat(executeFile)
|
|
if file_stat.st_mode & stat.S_IXUSR:
|
|
Upgrade.stdOut("✅ VERIFIED: Execute permission confirmed on Imunify360 file")
|
|
else:
|
|
Upgrade.stdOut("❌ VERIFICATION FAILED: Execute permission not set")
|
|
except Exception as verify_error:
|
|
Upgrade.stdOut(f"⚠️ Could not verify permissions: {str(verify_error)}")
|
|
else:
|
|
Upgrade.stdOut(f"⚠️ Imunify360 execute file not found: {executeFile}")
|
|
|
|
Upgrade.stdOut("=== FINAL STEP COMPLETE ===")
|
|
|
|
except Exception as e:
|
|
Upgrade.stdOut(f"❌ ERROR in final permission setting: {str(e)}")
|
|
|
|
Upgrade.installDNS_CyberPanelACMEFile()
|
|
|
|
command = 'systemctl restart fastapi_ssh_server'
|
|
Upgrade.executioner(command, command, 0)
|
|
|
|
Upgrade.stdOut("Upgrade Completed.")
|
|
|
|
### remove log file path incase its there
|
|
|
|
if Upgrade.SoftUpgrade:
|
|
time.sleep(30)
|
|
if os.path.exists(Upgrade.LogPathNew):
|
|
os.remove(Upgrade.LogPathNew)
|
|
|
|
@staticmethod
|
|
def fixApacheConfigurationOld():
|
|
"""OLD VERSION - DO NOT USE - Fix Apache configuration issues after upgrade"""
|
|
try:
|
|
# Check if Apache is installed
|
|
if Upgrade.FindOperatingSytem() == CENTOS7 or Upgrade.FindOperatingSytem() == CENTOS8 \
|
|
or Upgrade.FindOperatingSytem() == openEuler20 or Upgrade.FindOperatingSytem() == openEuler22:
|
|
apache_service = 'httpd'
|
|
apache_config_dir = '/etc/httpd'
|
|
else:
|
|
apache_service = 'apache2'
|
|
apache_config_dir = '/etc/apache2'
|
|
|
|
# Check if Apache is installed
|
|
check_apache = f'systemctl is-enabled {apache_service} 2>/dev/null'
|
|
result = subprocess.run(check_apache, shell=True, capture_output=True, text=True)
|
|
|
|
if result.returncode == 0:
|
|
Upgrade.stdOut("Fixing Apache configuration...")
|
|
|
|
# 1. Ensure Apache ports are correctly configured
|
|
command = 'grep -q "Listen 8083" /usr/local/lsws/conf/httpd_config.xml || echo "Apache port configuration might need manual check"'
|
|
Upgrade.executioner(command, 'Check Apache ports', 1)
|
|
|
|
# 2. Fix proxy rewrite rules for all vhosts
|
|
# The issue: Both rewrite rules execute, causing incorrect proxying
|
|
# Fix: Add proper HTTPS condition for SSL proxy rule
|
|
command = '''find /usr/local/lsws/conf/vhosts/ -name "vhost.conf" -exec sed -i '
|
|
/^REWRITERULE.*proxyApacheBackendSSL/i\\
|
|
RewriteCond %{HTTPS} =on
|
|
' {} \;'''
|
|
Upgrade.executioner(command, 'Fix Apache SSL proxy condition', 1)
|
|
|
|
# Also ensure the proxy backends are properly configured
|
|
command = '''grep -q "extprocessor apachebackend" /usr/local/lsws/conf/httpd_config.conf || echo "
|
|
extprocessor apachebackend {
|
|
type proxy
|
|
address http://127.0.0.1:8083
|
|
maxConns 100
|
|
initTimeout 60
|
|
retryTimeout 30
|
|
respBuffer 0
|
|
}
|
|
|
|
extprocessor proxyApacheBackendSSL {
|
|
type proxy
|
|
address https://127.0.0.1:8082
|
|
maxConns 100
|
|
initTimeout 60
|
|
retryTimeout 30
|
|
respBuffer 0
|
|
}" >> /usr/local/lsws/conf/httpd_config.conf'''
|
|
Upgrade.executioner(command, 'Ensure Apache proxy backends exist', 1)
|
|
|
|
# 3. Ensure Apache is configured to listen on correct ports
|
|
if Upgrade.FindOperatingSytem() in [CENTOS7, CENTOS8, openEuler20, openEuler22]:
|
|
apache_port_conf = '/etc/httpd/conf.d/00-port.conf'
|
|
else:
|
|
apache_port_conf = '/etc/apache2/ports.conf'
|
|
|
|
command = f'''
|
|
grep -q "Listen 8082" {apache_port_conf} || echo "Listen 8082" >> {apache_port_conf}
|
|
grep -q "Listen 8083" {apache_port_conf} || echo "Listen 8083" >> {apache_port_conf}
|
|
'''
|
|
Upgrade.executioner(command, 'Ensure Apache listens on 8082/8083', 1)
|
|
|
|
# 4. Restart Apache service
|
|
command = f'systemctl restart {apache_service}'
|
|
Upgrade.executioner(command, f'Restart {apache_service}', 1)
|
|
|
|
# 5. Fix PHP-FPM socket permissions and restart services
|
|
for version in ['5.4', '5.5', '5.6', '7.0', '7.1', '7.2', '7.3', '7.4', '8.0', '8.1', '8.2', '8.3']:
|
|
if Upgrade.FindOperatingSytem() in [CENTOS7, CENTOS8, openEuler20, openEuler22]:
|
|
php_service = f'php{version.replace(".", "")}-php-fpm'
|
|
socket_dir = '/var/run/php-fpm'
|
|
else:
|
|
php_service = f'php{version}-fpm'
|
|
socket_dir = '/var/run/php'
|
|
|
|
# Ensure socket directory exists with correct permissions
|
|
command = f'''
|
|
if systemctl is-active {php_service} >/dev/null 2>&1; then
|
|
mkdir -p {socket_dir}
|
|
chmod 755 {socket_dir}
|
|
systemctl restart {php_service}
|
|
fi
|
|
'''
|
|
Upgrade.executioner(command, f'Fix and restart {php_service}', 1)
|
|
|
|
# 6. Reload LiteSpeed to apply proxy changes
|
|
command = '/usr/local/lsws/bin/lswsctrl reload'
|
|
Upgrade.executioner(command, 'Reload LiteSpeed', 1)
|
|
|
|
Upgrade.stdOut("Apache configuration fixes completed.")
|
|
else:
|
|
Upgrade.stdOut("Apache not detected, skipping Apache fixes.")
|
|
|
|
except Exception as e:
|
|
Upgrade.stdOut(f"Error fixing Apache configuration: {str(e)}")
|
|
pass
|
|
|
|
@staticmethod
|
|
def installQuota():
|
|
try:
|
|
|
|
if Upgrade.FindOperatingSytem() == CENTOS7 or Upgrade.FindOperatingSytem() == CENTOS8\
|
|
or Upgrade.FindOperatingSytem() == openEuler20 or Upgrade.FindOperatingSytem() == openEuler22:
|
|
command = "yum install quota -y"
|
|
Upgrade.executioner(command, command, 0, True)
|
|
|
|
if Upgrade.edit_fstab('/', '/') == 0:
|
|
print("Quotas will not be abled as we failed to modify fstab file.")
|
|
return 0
|
|
|
|
|
|
command = 'mount -o remount /'
|
|
try:
|
|
mResult = subprocess.run(command, capture_output=True, universal_newlines=True, shell=True)
|
|
except:
|
|
mResult = subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
|
|
universal_newlines=True, shell=True)
|
|
|
|
if mResult.returncode != 0:
|
|
fstab_path = '/etc/fstab'
|
|
backup_path = fstab_path + '.bak'
|
|
if os.path.exists(fstab_path):
|
|
os.remove(fstab_path)
|
|
shutil.copy(backup_path, fstab_path)
|
|
|
|
print("Re-mount failed, restoring original FSTab and existing quota setup.")
|
|
return 0
|
|
|
|
##
|
|
|
|
if Upgrade.FindOperatingSytem() == Ubuntu22 or Upgrade.FindOperatingSytem() == Ubuntu24 or Upgrade.FindOperatingSytem() == Ubuntu18 \
|
|
or Upgrade.FindOperatingSytem() == Ubuntu20 or Upgrade.FindOperatingSytem() == Debian11 or Upgrade.FindOperatingSytem() == Debian12 or Upgrade.FindOperatingSytem() == Debian13:
|
|
|
|
print("Install Quota on Ubuntu")
|
|
command = 'apt update -y'
|
|
Upgrade.executioner(command, command, 0, True)
|
|
|
|
command = 'apt install quota -y'
|
|
Upgrade.executioner(command, command, 0, True)
|
|
|
|
command = "find /lib/modules/ -type f -name '*quota_v*.ko*'"
|
|
|
|
try:
|
|
output = subprocess.check_output(command, shell=True)
|
|
if output and output.decode("utf-8").find("quota/") == -1:
|
|
command = "sudo apt install linux-image-extra-virtual -y"
|
|
Upgrade.executioner(command, command, 0, True)
|
|
except Exception as e:
|
|
Upgrade.stdOut(f"Error checking quota modules: {str(e)}")
|
|
|
|
if Upgrade.edit_fstab('/', '/') == 0:
|
|
print("Quotas will not be abled as we are are failed to modify fstab file.")
|
|
return 0
|
|
|
|
command = 'mount -o remount /'
|
|
try:
|
|
mResult = subprocess.run(command, capture_output=True, universal_newlines=True, shell=True)
|
|
except:
|
|
mResult = subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
|
|
universal_newlines=True, shell=True)
|
|
if mResult.returncode != 0:
|
|
fstab_path = '/etc/fstab'
|
|
backup_path = fstab_path + '.bak'
|
|
if os.path.exists(fstab_path):
|
|
os.remove(fstab_path)
|
|
shutil.copy(backup_path, fstab_path)
|
|
|
|
print("Re-mount failed, restoring original FSTab and existing quota setup.")
|
|
return 0
|
|
|
|
command = 'quotacheck -ugm /'
|
|
try:
|
|
mResult = subprocess.run(command, capture_output=True, universal_newlines=True, shell=True)
|
|
except:
|
|
mResult = subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
|
|
universal_newlines=True, shell=True)
|
|
if mResult.returncode != 0:
|
|
fstab_path = '/etc/fstab'
|
|
backup_path = fstab_path + '.bak'
|
|
if os.path.exists(fstab_path):
|
|
os.remove(fstab_path)
|
|
shutil.copy(backup_path, fstab_path)
|
|
|
|
print("Re-mount failed, restoring original FSTab and existing quota setup.")
|
|
return 0
|
|
|
|
####
|
|
|
|
command = "find /lib/modules/ -type f -name '*quota_v*.ko*'"
|
|
try:
|
|
iResult = subprocess.run(command, capture_output=True, universal_newlines=True, shell=True)
|
|
except:
|
|
iResult = subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
|
|
universal_newlines=True, shell=True)
|
|
print(repr(iResult.stdout))
|
|
|
|
# Only if the first command works, run the rest
|
|
|
|
if iResult.returncode == 0:
|
|
command = "echo '{}' | sed -n 's|/lib/modules/\\([^/]*\\)/.*|\\1|p' | sort -u".format(iResult.stdout)
|
|
try:
|
|
result = subprocess.run(command, capture_output=True, universal_newlines=True, shell=True)
|
|
except:
|
|
result = subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
|
|
universal_newlines=True, shell=True)
|
|
fResult = result.stdout.rstrip('\n')
|
|
print(repr(result.stdout.rstrip('\n')))
|
|
|
|
command = 'uname -r'
|
|
try:
|
|
ffResult = subprocess.run(command, capture_output=True, universal_newlines=True, shell=True)
|
|
except:
|
|
ffResult = subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
|
|
universal_newlines=True, shell=True)
|
|
ffResult = ffResult.stdout.rstrip('\n')
|
|
|
|
command = f"apt-get install linux-modules-extra-{ffResult}"
|
|
Upgrade.executioner(command, command, 0, True)
|
|
|
|
###
|
|
|
|
command = f'modprobe quota_v1 -S {ffResult}'
|
|
try:
|
|
mResult = subprocess.run(command, capture_output=True, universal_newlines=True, shell=True)
|
|
except:
|
|
mResult = subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
|
|
universal_newlines=True, shell=True)
|
|
if mResult.returncode != 0:
|
|
fstab_path = '/etc/fstab'
|
|
backup_path = fstab_path + '.bak'
|
|
if os.path.exists(fstab_path):
|
|
os.remove(fstab_path)
|
|
shutil.copy(backup_path, fstab_path)
|
|
|
|
print("Re-mount failed, restoring original FSTab and existing quota setup.")
|
|
return 0
|
|
|
|
command = f'modprobe quota_v2 -S {ffResult}'
|
|
try:
|
|
mResult = subprocess.run(command, capture_output=True, universal_newlines=True, shell=True)
|
|
except:
|
|
mResult = subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
|
|
universal_newlines=True, shell=True)
|
|
if mResult.returncode != 0:
|
|
fstab_path = '/etc/fstab'
|
|
backup_path = fstab_path + '.bak'
|
|
if os.path.exists(fstab_path):
|
|
os.remove(fstab_path)
|
|
shutil.copy(backup_path, fstab_path)
|
|
|
|
print("Re-mount failed, restoring original FSTab and existing quota setup.")
|
|
return 0
|
|
|
|
command = f'quotacheck -ugm /'
|
|
try:
|
|
mResult = subprocess.run(command, capture_output=True, universal_newlines=True, shell=True)
|
|
except:
|
|
mResult = subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
|
|
universal_newlines=True, shell=True)
|
|
if mResult.returncode != 0:
|
|
fstab_path = '/etc/fstab'
|
|
backup_path = fstab_path + '.bak'
|
|
if os.path.exists(fstab_path):
|
|
os.remove(fstab_path)
|
|
shutil.copy(backup_path, fstab_path)
|
|
|
|
print("Re-mount failed, restoring original FSTab and existing quota setup.")
|
|
return 0
|
|
|
|
command = f'quotaon -v /'
|
|
try:
|
|
mResult = subprocess.run(command, capture_output=True, universal_newlines=True, shell=True)
|
|
except:
|
|
mResult = subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
|
|
universal_newlines=True, shell=True)
|
|
if mResult.returncode != 0:
|
|
fstab_path = '/etc/fstab'
|
|
backup_path = fstab_path + '.bak'
|
|
if os.path.exists(fstab_path):
|
|
os.remove(fstab_path)
|
|
shutil.copy(backup_path, fstab_path)
|
|
|
|
print("Re-mount failed, restoring original FSTab and existing quota setup.")
|
|
return 0
|
|
|
|
return 1
|
|
|
|
except Exception as e:
|
|
ErrorSanitizer.log_error_securely(e, 'installQuota')
|
|
print("[ERROR] installQuota. Failed to install quota")
|
|
return 0
|
|
|
|
@staticmethod
|
|
def edit_fstab(mount_point, options_to_add):
|
|
try:
|
|
retValue = 1
|
|
# Backup the original fstab file
|
|
fstab_path = '/etc/fstab'
|
|
backup_path = fstab_path + '.bak'
|
|
|
|
rData = open(fstab_path, 'r').read()
|
|
|
|
if rData.find('xfs') > -1:
|
|
options_to_add = 'uquota'
|
|
else:
|
|
options_to_add = 'usrquota,grpquota'
|
|
|
|
if not os.path.exists(backup_path):
|
|
shutil.copy(fstab_path, backup_path)
|
|
|
|
# Read the fstab file
|
|
with open(fstab_path, 'r') as file:
|
|
lines = file.readlines()
|
|
|
|
# Modify the appropriate line
|
|
WriteToFile = open(fstab_path, 'w')
|
|
for i, line in enumerate(lines):
|
|
|
|
if line.find('\t') > -1:
|
|
parts = line.split('\t')
|
|
else:
|
|
parts = line.split(' ')
|
|
|
|
print(parts)
|
|
try:
|
|
if parts[1] == '/' and parts[3].find(options_to_add) == -1 and len(parts[3]) > 4:
|
|
|
|
parts[3] = f'{parts[3]},{options_to_add}'
|
|
tempParts = [item for item in parts if item.strip()]
|
|
finalString = '\t'.join(tempParts)
|
|
print(finalString)
|
|
WriteToFile.write(finalString)
|
|
|
|
elif parts[1] == '/':
|
|
|
|
for ii, p in enumerate(parts):
|
|
if p.find('defaults') > -1 or p.find('discard') > -1 or p.find('errors=') > -1:
|
|
parts[ii] = f'{parts[ii]},{options_to_add}'
|
|
tempParts = [item for item in parts if item.strip()]
|
|
finalString = '\t'.join(tempParts)
|
|
print(finalString)
|
|
WriteToFile.write(finalString)
|
|
else:
|
|
WriteToFile.write(line)
|
|
except:
|
|
WriteToFile.write(line)
|
|
|
|
WriteToFile.close()
|
|
|
|
return retValue
|
|
except:
|
|
return 0
|
|
|
|
|
|
@staticmethod
|
|
def FixCurrentQuoatasSystem():
|
|
fstab_path = '/etc/fstab'
|
|
|
|
data = open(fstab_path, 'r').read()
|
|
|
|
if data.find("usrquota,grpquota") > -1 or data.find("uquota") > -1:
|
|
print("Quotas already enabled.")
|
|
|
|
|
|
if Upgrade.installQuota() == 1:
|
|
|
|
print("We will attempt to bring new Quota system to old websites.")
|
|
from websiteFunctions.models import Websites
|
|
for website in Websites.objects.all():
|
|
|
|
command = 'chattr -R -i /home/%s/' % (website.domain)
|
|
Upgrade.executioner(command, command, 0, True)
|
|
|
|
if website.package.enforceDiskLimits:
|
|
spaceString = f'{website.package.diskSpace}M {website.package.diskSpace}M'
|
|
command = f'setquota -u {website.externalApp} {spaceString} 0 0 /'
|
|
Upgrade.executioner(command, command, 0, True)
|
|
|
|
else:
|
|
print("Quotas can not be enabled continue to use chhtr.")
|
|
|
|
@staticmethod
|
|
def installDNS_CyberPanelACMEFile():
|
|
filePath = '/root/.acme.sh/dns_cyberpanel.sh'
|
|
if os.path.exists(filePath):
|
|
os.remove(filePath)
|
|
shutil.copy('/usr/local/CyberCP/install/dns_cyberpanel.sh', filePath)
|
|
|
|
command = f'chmod +x {filePath}'
|
|
Upgrade.executioner(command, command, 0, True)
|
|
|
|
@staticmethod
|
|
def fixApacheConfiguration():
|
|
"""
|
|
Fix Apache configuration issues after upgrade, particularly for 503 errors
|
|
when Apache is used as reverse proxy to OpenLiteSpeed
|
|
"""
|
|
try:
|
|
print("Starting Apache configuration fix...")
|
|
|
|
# Check if Apache is installed
|
|
osType = Upgrade.FindOperatingSytem()
|
|
if osType in [CENTOS7, CENTOS8, CloudLinux7, CloudLinux8]:
|
|
configBasePath = '/etc/httpd/conf.d/'
|
|
serviceName = 'httpd'
|
|
else:
|
|
configBasePath = '/etc/apache2/sites-enabled/'
|
|
serviceName = 'apache2'
|
|
|
|
if not os.path.exists(configBasePath):
|
|
print("Apache not installed, skipping Apache fixes.")
|
|
return
|
|
|
|
# Import required modules
|
|
from websiteFunctions.models import Websites
|
|
import re
|
|
|
|
# Fix 1: Update Apache proxy configurations for domains actually using Apache
|
|
print("Fixing Apache proxy configurations...")
|
|
fixed_count = 0
|
|
apache_domains = []
|
|
|
|
# First, identify which domains are using Apache by checking for Apache vhost configs
|
|
for config_file in os.listdir(configBasePath):
|
|
if config_file.endswith('.conf'):
|
|
# Extract domain name from config file
|
|
domain_name = config_file.replace('.conf', '')
|
|
config_path = os.path.join(configBasePath, config_file)
|
|
|
|
try:
|
|
# Read the configuration to verify it's an Apache proxy setup
|
|
with open(config_path, 'r') as f:
|
|
content = f.read()
|
|
|
|
# Check if this is actually an Apache proxy configuration
|
|
# Look for common Apache proxy indicators
|
|
is_apache_proxy = False
|
|
if 'ProxyPass' in content and ('127.0.0.1:8082' in content or '127.0.0.1:8083' in content):
|
|
is_apache_proxy = True
|
|
elif 'RewriteRule' in content and 'apachebackend' in content:
|
|
is_apache_proxy = True
|
|
elif '<FilesMatch' in content and 'SetHandler' in content and 'proxy:unix:' in content:
|
|
is_apache_proxy = True
|
|
|
|
if is_apache_proxy:
|
|
apache_domains.append(domain_name)
|
|
modified = False
|
|
|
|
# Fix the proxy rewrite rules - add missing HTTPS condition
|
|
if 'RewriteRule ^/(.*)$ http://apachebackend/$1 [P,L]' in content and 'RewriteCond %{HTTPS} off' not in content:
|
|
# Find the RewriteRule for HTTP proxy
|
|
lines = content.split('\n')
|
|
new_lines = []
|
|
i = 0
|
|
while i < len(lines):
|
|
line = lines[i]
|
|
if 'RewriteRule ^/(.*)$ http://apachebackend/$1 [P,L]' in line:
|
|
# Add the missing HTTPS condition before the rule
|
|
indent = len(line) - len(line.lstrip())
|
|
new_lines.append(' ' * indent + 'RewriteCond %{HTTPS} off')
|
|
new_lines.append(line)
|
|
modified = True
|
|
else:
|
|
new_lines.append(line)
|
|
i += 1
|
|
|
|
if modified:
|
|
content = '\n'.join(new_lines)
|
|
|
|
# Write back if modified
|
|
if modified:
|
|
with open(config_path, 'w') as f:
|
|
f.write(content)
|
|
fixed_count += 1
|
|
print(f"Fixed Apache configuration for: {config_file}")
|
|
|
|
except Exception as e:
|
|
print(f"Error processing {config_file}: {str(e)}")
|
|
|
|
print(f"Found {len(apache_domains)} domains using Apache")
|
|
print(f"Fixed {fixed_count} Apache configurations.")
|
|
|
|
# If no domains are using Apache, skip the rest of the fixes
|
|
if len(apache_domains) == 0:
|
|
print("No domains found using Apache as reverse proxy. Skipping remaining Apache fixes.")
|
|
return
|
|
|
|
# Fix 2: Ensure Apache proxy backends are configured in OLS/LSWS
|
|
print("Checking OpenLiteSpeed proxy backend configurations...")
|
|
lsws_config = "/usr/local/lsws/conf/httpd_config.conf"
|
|
|
|
if os.path.exists(lsws_config):
|
|
with open(lsws_config, 'r') as f:
|
|
lsws_content = f.read()
|
|
|
|
modified = False
|
|
|
|
# Check for apachebackend extprocessor
|
|
if 'extprocessor apachebackend' not in lsws_content:
|
|
# Add apachebackend configuration
|
|
backend_config = '''
|
|
extprocessor apachebackend {
|
|
type proxy
|
|
address 127.0.0.1:8082
|
|
maxConns 100
|
|
initTimeout 60
|
|
retryTimeout 60
|
|
respBuffer 0
|
|
}
|
|
'''
|
|
lsws_content += backend_config
|
|
modified = True
|
|
print("Added apachebackend extprocessor configuration")
|
|
|
|
# Check for proxyApacheBackendSSL extprocessor
|
|
if 'extprocessor proxyApacheBackendSSL' not in lsws_content:
|
|
# Add proxyApacheBackendSSL configuration
|
|
ssl_backend_config = '''
|
|
extprocessor proxyApacheBackendSSL {
|
|
type proxy
|
|
address https://127.0.0.1:8083
|
|
maxConns 100
|
|
initTimeout 60
|
|
retryTimeout 60
|
|
respBuffer 0
|
|
}
|
|
'''
|
|
lsws_content += ssl_backend_config
|
|
modified = True
|
|
print("Added proxyApacheBackendSSL extprocessor configuration")
|
|
|
|
if modified:
|
|
with open(lsws_config, 'w') as f:
|
|
f.write(lsws_content)
|
|
print("Updated OpenLiteSpeed configuration with Apache proxy backends")
|
|
|
|
# Fix 3: Create/Update .htaccess files ONLY for domains actually using Apache
|
|
print("Creating/Updating .htaccess files for Apache domains...")
|
|
htaccess_fixed = 0
|
|
htaccess_created = 0
|
|
|
|
# Only process domains that we confirmed are using Apache
|
|
for domain in apache_domains:
|
|
try:
|
|
htaccess_path = f'/home/{domain}/public_html/.htaccess'
|
|
|
|
# Check if .htaccess exists
|
|
if os.path.exists(htaccess_path):
|
|
with open(htaccess_path, 'r') as f:
|
|
htaccess_content = f.read()
|
|
|
|
# Check if it's an Apache proxy configuration (case insensitive)
|
|
if 'apachebackend' in htaccess_content.lower():
|
|
# Check if it has proper HTTP/HTTPS handling
|
|
needs_update = False
|
|
|
|
# Check for old style single rule
|
|
if 'REWRITERULE ^(.*)$ HTTP://apachebackend/$1 [P]' in htaccess_content:
|
|
needs_update = True
|
|
# Check if missing HTTPS conditions
|
|
elif 'RewriteCond %{HTTPS} off' not in htaccess_content or 'proxyApacheBackendSSL' not in htaccess_content:
|
|
needs_update = True
|
|
|
|
if needs_update:
|
|
# Create proper .htaccess with both HTTP and HTTPS handling
|
|
new_htaccess = '''RewriteEngine On
|
|
|
|
# HTTP to backend
|
|
RewriteCond %{HTTPS} off
|
|
RewriteRule ^(.*)$ http://apachebackend/$1 [P,L]
|
|
|
|
# HTTPS to SSL backend
|
|
RewriteCond %{HTTPS} on
|
|
RewriteRule ^(.*)$ https://proxyApacheBackendSSL/$1 [P,L]
|
|
'''
|
|
with open(htaccess_path, 'w') as f:
|
|
f.write(new_htaccess)
|
|
htaccess_fixed += 1
|
|
print(f"Fixed .htaccess for: {domain}")
|
|
else:
|
|
# .htaccess doesn't exist - this domain might be missing it!
|
|
# Create the proper .htaccess file
|
|
print(f"Creating missing .htaccess for Apache domain: {domain}")
|
|
|
|
# Ensure public_html exists
|
|
public_html_path = f'/home/{domain}/public_html'
|
|
if os.path.exists(public_html_path):
|
|
new_htaccess = '''RewriteEngine On
|
|
|
|
# HTTP to backend
|
|
RewriteCond %{HTTPS} off
|
|
RewriteRule ^(.*)$ http://apachebackend/$1 [P,L]
|
|
|
|
# HTTPS to SSL backend
|
|
RewriteCond %{HTTPS} on
|
|
RewriteRule ^(.*)$ https://proxyApacheBackendSSL/$1 [P,L]
|
|
'''
|
|
with open(htaccess_path, 'w') as f:
|
|
f.write(new_htaccess)
|
|
|
|
# Set proper permissions
|
|
try:
|
|
website = Websites.objects.get(domain=domain)
|
|
command = f'chown {website.externalApp}:{website.externalApp} {htaccess_path}'
|
|
Upgrade.executioner(command, command, 0, True)
|
|
except:
|
|
pass
|
|
|
|
htaccess_created += 1
|
|
print(f"Created .htaccess for: {domain}")
|
|
else:
|
|
print(f"Warning: public_html not found for domain: {domain}")
|
|
|
|
except Exception as e:
|
|
print(f"Error updating .htaccess for {domain}: {str(e)}")
|
|
|
|
print(f"Fixed {htaccess_fixed} .htaccess files.")
|
|
print(f"Created {htaccess_created} missing .htaccess files.")
|
|
|
|
# Fix 3b: Also fix OpenLiteSpeed vhost configurations that might have incorrect rewrite rules
|
|
print("Fixing OpenLiteSpeed vhost configurations for Apache domains...")
|
|
ols_fixed = 0
|
|
|
|
for domain in apache_domains:
|
|
try:
|
|
ols_vhost_path = f'/usr/local/lsws/conf/vhosts/{domain}/vhost.conf'
|
|
|
|
if os.path.exists(ols_vhost_path):
|
|
with open(ols_vhost_path, 'r') as f:
|
|
vhost_content = f.read()
|
|
|
|
# Check if it has the incorrect rewrite rules
|
|
if 'RewriteCond %{HTTPS} !=on' in vhost_content and 'HTTP://proxyApacheBackendSSL' in vhost_content:
|
|
# This has the buggy configuration where HTTPS rule doesn't have proper condition
|
|
modified = False
|
|
|
|
# Replace the buggy rewrite section
|
|
buggy_pattern = r'rewrite\s*{\s*enable\s*1\s*rules\s*<<<END_rules\s*RewriteEngine On\s*RewriteCond %{HTTPS}\s*!=on\s*REWRITERULE \^\(\.\*\)\$ HTTP://apachebackend/\$1 \[P,L\]\s*REWRITERULE \^\(\.\*\)\$ HTTP://proxyApacheBackendSSL/\$1 \[P,L\]\s*END_rules\s*}'
|
|
|
|
correct_rewrite = '''rewrite {
|
|
enable 1
|
|
rules <<<END_rules
|
|
RewriteEngine On
|
|
RewriteCond %{HTTPS} off
|
|
RewriteRule ^(.*)$ http://apachebackend/$1 [P,L]
|
|
RewriteCond %{HTTPS} on
|
|
RewriteRule ^(.*)$ https://proxyApacheBackendSSL/$1 [P,L]
|
|
END_rules
|
|
}'''
|
|
|
|
# Use a simpler approach - find and replace the section
|
|
import re
|
|
if isinstance(vhost_content, str) and vhost_content:
|
|
new_content = re.sub(
|
|
r'rewrite\s*{[^}]+}',
|
|
correct_rewrite,
|
|
vhost_content,
|
|
count=1
|
|
)
|
|
else:
|
|
new_content = vhost_content
|
|
|
|
if new_content != vhost_content:
|
|
with open(ols_vhost_path, 'w') as f:
|
|
f.write(new_content)
|
|
ols_fixed += 1
|
|
print(f"Fixed OLS vhost configuration for: {domain}")
|
|
|
|
except Exception as e:
|
|
print(f"Error fixing OLS vhost for {domain}: {str(e)}")
|
|
|
|
if ols_fixed > 0:
|
|
print(f"Fixed {ols_fixed} OpenLiteSpeed vhost configurations.")
|
|
|
|
# Fix 4: Ensure Apache is listening on correct ports
|
|
if osType in [CENTOS7, CENTOS8, CloudLinux7, CloudLinux8]:
|
|
apache_conf = '/etc/httpd/conf/httpd.conf'
|
|
else:
|
|
ports_conf = '/etc/apache2/ports.conf'
|
|
apache_conf = ports_conf if os.path.exists(ports_conf) else '/etc/apache2/apache2.conf'
|
|
|
|
if os.path.exists(apache_conf):
|
|
with open(apache_conf, 'r') as f:
|
|
conf_content = f.read()
|
|
|
|
# Check if Apache is configured to listen on 8082 and 8083
|
|
if 'Listen 8082' not in conf_content or 'Listen 8083' not in conf_content:
|
|
print("Fixing Apache listen ports...")
|
|
|
|
# For Ubuntu/Debian, update ports.conf
|
|
if osType not in [CENTOS7, CENTOS8, CloudLinux7, CloudLinux8]:
|
|
if os.path.exists('/etc/apache2/ports.conf'):
|
|
with open('/etc/apache2/ports.conf', 'w') as f:
|
|
f.write('Listen 8082\nListen 8083\n')
|
|
else:
|
|
# For CentOS, update httpd.conf
|
|
lines = conf_content.split('\n')
|
|
new_lines = []
|
|
listen_added = False
|
|
|
|
for line in lines:
|
|
if line.strip().startswith('Listen') and '80' in line and not listen_added:
|
|
new_lines.append('Listen 8082')
|
|
new_lines.append('Listen 8083')
|
|
listen_added = True
|
|
elif 'Listen 8082' not in line and 'Listen 8083' not in line:
|
|
new_lines.append(line)
|
|
|
|
with open(apache_conf, 'w') as f:
|
|
f.write('\n'.join(new_lines))
|
|
|
|
print("Fixed Apache listen ports")
|
|
|
|
# Fix 5: Fix PHP-FPM socket permissions
|
|
print("Fixing PHP-FPM socket permissions...")
|
|
if osType in [CENTOS7, CENTOS8, CloudLinux7, CloudLinux8]:
|
|
sock_path = '/var/run/php-fpm/'
|
|
else:
|
|
sock_path = '/var/run/php/'
|
|
|
|
if os.path.exists(sock_path):
|
|
# Set proper permissions
|
|
command = f'chmod 755 {sock_path}'
|
|
Upgrade.executioner(command, command, 0, True)
|
|
|
|
# Fix ownership
|
|
command = f'chown apache:apache {sock_path}' if osType in [CENTOS7, CENTOS8, CloudLinux7, CloudLinux8] else f'chown www-data:www-data {sock_path}'
|
|
Upgrade.executioner(command, command, 0, True)
|
|
|
|
# Restart services
|
|
print("Restarting services...")
|
|
|
|
# Restart Apache
|
|
command = f'systemctl restart {serviceName}'
|
|
Upgrade.executioner(command, command, 0, True)
|
|
|
|
# Restart OpenLiteSpeed
|
|
command = 'systemctl restart lsws'
|
|
Upgrade.executioner(command, command, 0, True)
|
|
|
|
# Restart PHP-FPM services
|
|
if osType in [CENTOS7, CENTOS8, CloudLinux7, CloudLinux8]:
|
|
for version in ['54', '55', '56', '70', '71', '72', '73', '74', '80', '81', '82', '83', '84']:
|
|
command = f'systemctl restart php{version}-php-fpm'
|
|
Upgrade.executioner(command, command, 0, True)
|
|
else:
|
|
for version in ['5.6', '7.0', '7.1', '7.2', '7.3', '7.4', '8.0', '8.1', '8.2', '8.3']:
|
|
command = f'systemctl restart php{version}-fpm'
|
|
Upgrade.executioner(command, command, 0, True)
|
|
|
|
print("Apache configuration fix completed successfully!")
|
|
|
|
except Exception as e:
|
|
print(f"Error during Apache configuration fix: {str(e)}")
|
|
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(description='CyberPanel Installer')
|
|
parser.add_argument('branch', help='Install from branch name.')
|
|
|
|
args = parser.parse_args()
|
|
|
|
Upgrade.upgrade(args.branch)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|