mirror of
https://github.com/usmannasir/cyberpanel.git
synced 2026-06-26 20:00:28 +02:00
Merge branch 'v2.3.4-dev' of https://github.com/usmannasir/cyberpanel into v2.3.4-dev
This commit is contained in:
@@ -75,14 +75,13 @@ class cyberPanel:
|
||||
logger.writeforCLI(str(msg), "Error", stack()[0][3])
|
||||
self.printStatus(0, str(msg))
|
||||
|
||||
def createDomain(self, masterDomain, domainName, owner, php, ssl, dkim, openBasedir):
|
||||
def createDomain(self, masterDomain, domainName, owner, php, ssl, dkim, openBasedir, path):
|
||||
try:
|
||||
|
||||
path = '/home/' + masterDomain + '/public_html/' + domainName
|
||||
complete_path = '/home/' + masterDomain + '/' + path
|
||||
phpSelection = 'PHP ' + php
|
||||
|
||||
result = virtualHostUtilities.createDomain(masterDomain, domainName, phpSelection, path, ssl, dkim,
|
||||
openBasedir, owner, 0)
|
||||
result = virtualHostUtilities.createDomain(masterDomain, domainName, phpSelection, complete_path, ssl, dkim, openBasedir, owner, 0)
|
||||
|
||||
if result[0] == 1:
|
||||
self.printStatus(1, 'None')
|
||||
@@ -920,8 +919,13 @@ def main():
|
||||
openBasedir = int(args.openBasedir)
|
||||
else:
|
||||
openBasedir = 0
|
||||
|
||||
if args.path:
|
||||
path = args.path
|
||||
else:
|
||||
path = "public_html/" + args.childDomain
|
||||
|
||||
cyberpanel.createDomain(args.masterDomain, args.childDomain, args.owner, args.php, ssl, dkim, openBasedir)
|
||||
cyberpanel.createDomain(args.masterDomain, args.childDomain, args.owner, args.php, ssl, dkim, openBasedir, path)
|
||||
elif args.function == "deleteChild":
|
||||
|
||||
completeCommandExample = 'cyberpanel deleteChild --childDomain cyberpanel.net'
|
||||
|
||||
@@ -44,6 +44,17 @@ class CPBackupsV2:
|
||||
## Set up the repo name to be used
|
||||
|
||||
self.repo = f"rclone:{self.data['BackendName']}:{self.data['domain']}"
|
||||
self.snapshots = []
|
||||
|
||||
|
||||
def FetchSnapShots(self):
|
||||
try:
|
||||
command = f'rustic -r {self.repo} snapshots --password "" --json 2>/dev/null'
|
||||
result = json.loads(
|
||||
ProcessUtilities.outputExecutioner(command, self.website.externalApp, True).rstrip('\n'))
|
||||
return 1, result
|
||||
except BaseException as msg:
|
||||
return 0, str(msg)
|
||||
|
||||
def SetupRcloneBackend(self, type, config):
|
||||
self.LocalRclonePath = f'/home/{self.website.domain}/.config/rclone'
|
||||
@@ -113,9 +124,8 @@ pass = {ObsecurePassword}
|
||||
self.buv2.website.BackupLock = 0
|
||||
self.buv2.website.save()
|
||||
|
||||
|
||||
## parent is used to link this snapshot with master snapshot
|
||||
def BackupConfig(self, parent):
|
||||
def BackupConfig(self):
|
||||
### Backup config file to rustic
|
||||
|
||||
command = f'chown {self.website.externalApp}:{self.website.externalApp} {self.FinalPathRuctic}'
|
||||
@@ -127,9 +137,38 @@ pass = {ObsecurePassword}
|
||||
#command = f'chown cyberpanel:cyberpanel {self.FinalPathRuctic}'
|
||||
#ProcessUtilities.executioner(command)
|
||||
|
||||
command = f'rustic -r {self.repo} backup {self.FinalPathRuctic}/config.json --password "" --parent {parent}'
|
||||
command = f'chown {self.website.externalApp}:{self.website.externalApp} {self.FinalPathRuctic}/config.json'
|
||||
ProcessUtilities.executioner(command)
|
||||
|
||||
command = f'rustic -r {self.repo} backup {self.FinalPathRuctic}/config.json --json --password "" 2>/dev/null'
|
||||
result = json.loads(ProcessUtilities.outputExecutioner(command, self.website.externalApp, True).rstrip('\n'))
|
||||
|
||||
try:
|
||||
SnapShotID = result['id'] ## snapshot id that we need to store in db
|
||||
files_new = result['summary']['files_new'] ## basically new files in backup
|
||||
total_duration = result['summary']['total_duration'] ## time taken
|
||||
|
||||
self.snapshots.append(SnapShotID)
|
||||
|
||||
except BaseException as msg:
|
||||
self.UpdateStatus(f'Backup failed as no snapshot id found, error: {str(msg)}', CPBackupsV2.FAILED)
|
||||
return 0
|
||||
|
||||
command = f'chown cyberpanel:cyberpanel {self.FinalPathRuctic}/config.json'
|
||||
ProcessUtilities.executioner(command)
|
||||
|
||||
def MergeSnapshots(self):
|
||||
snapshots = ''
|
||||
for snapshot in self.snapshots:
|
||||
snapshots= f'{snapshots} {snapshot}'
|
||||
|
||||
|
||||
command = f'rustic -r {self.repo} merge {snapshots} --password "" --json 2>/dev/null'
|
||||
result = json.loads(ProcessUtilities.outputExecutioner(command, self.website.externalApp, True).rstrip('\n'))
|
||||
|
||||
command = f'rustic -r {self.repo} forget {snapshots} --password ""'
|
||||
result = ProcessUtilities.outputExecutioner(command, self.website.externalApp, True)
|
||||
|
||||
def InitiateBackup(self):
|
||||
|
||||
from websiteFunctions.models import Websites, Backupsv2
|
||||
@@ -302,6 +341,9 @@ pass = {ObsecurePassword}
|
||||
#command = f"echo '{json.dumps(Config)}' > {self.FinalPath}/config.json"
|
||||
#ProcessUtilities.executioner(command, self.website.externalApp, True)
|
||||
|
||||
command = f'chown cyberpanel:cyberpanel {self.FinalPathRuctic}/config.json'
|
||||
ProcessUtilities.executioner(command)
|
||||
|
||||
WriteToFile = open(f'{self.FinalPathRuctic}/config.json', 'w')
|
||||
WriteToFile.write(json.dumps(Config))
|
||||
WriteToFile.close()
|
||||
@@ -309,6 +351,8 @@ pass = {ObsecurePassword}
|
||||
command = f"chmod 600 {self.FinalPathRuctic}/config.json"
|
||||
ProcessUtilities.executioner(command)
|
||||
|
||||
self.BackupConfig()
|
||||
|
||||
|
||||
self.UpdateStatus('Backup config created,5', CPBackupsV2.RUNNING)
|
||||
except BaseException as msg:
|
||||
@@ -330,24 +374,26 @@ pass = {ObsecurePassword}
|
||||
return 0
|
||||
self.UpdateStatus('Website data backup completed successfully..,70', CPBackupsV2.RUNNING)
|
||||
|
||||
if self.data['BackupEmails']:
|
||||
self.UpdateStatus('Backing up emails..,75', CPBackupsV2.RUNNING)
|
||||
if self.BackupEmailsRustic() == 0:
|
||||
return 0
|
||||
self.UpdateStatus('Emails backup completed successfully..,85', CPBackupsV2.RUNNING)
|
||||
# if self.data['BackupEmails']:
|
||||
# self.UpdateStatus('Backing up emails..,75', CPBackupsV2.RUNNING)
|
||||
# if self.BackupEmailsRustic() == 0:
|
||||
# return 0
|
||||
# self.UpdateStatus('Emails backup completed successfully..,85', CPBackupsV2.RUNNING)
|
||||
|
||||
### Finally change the backup rustic folder to the website user owner
|
||||
|
||||
command = f'chown {self.website.externalApp}:{self.website.externalApp} {self.FinalPathRuctic}'
|
||||
ProcessUtilities.executioner(command)
|
||||
|
||||
self.MergeSnapshots()
|
||||
|
||||
self.UpdateStatus('Completed', CPBackupsV2.COMPLETED)
|
||||
|
||||
print(self.FinalPath)
|
||||
|
||||
break
|
||||
except BaseException as msg:
|
||||
self.UpdateStatus(f'Failed after config generation, Error: {str(msg)}', CPBackupsV2.FAILED)
|
||||
self.UpdateStatus(f'Failed, Error: {str(msg)}', CPBackupsV2.FAILED)
|
||||
return 0
|
||||
else:
|
||||
time.sleep(5)
|
||||
@@ -420,42 +466,50 @@ pass = {ObsecurePassword}
|
||||
|
||||
CurrentDBPath = f"{self.FinalPathRuctic}/{key}.sql"
|
||||
|
||||
DBResult = mysqlUtilities.createDatabaseBackup(key, self.FinalPathRuctic)
|
||||
DBResult, SnapID = mysqlUtilities.createDatabaseBackup(key, self.FinalPathRuctic, 1, self.repo, self.website.externalApp)
|
||||
|
||||
|
||||
if DBResult == 1:
|
||||
self.snapshots.append(SnapID)
|
||||
|
||||
command = f'chown {self.website.externalApp}:{self.website.externalApp} {CurrentDBPath}'
|
||||
ProcessUtilities.executioner(command)
|
||||
#command = f'chown {self.website.externalApp}:{self.website.externalApp} {CurrentDBPath}'
|
||||
#ProcessUtilities.executioner(command)
|
||||
|
||||
command = f'rustic -r {self.repo} backup {CurrentDBPath} --password "" --json 2>/dev/null'
|
||||
print(f'db command rustic: {command}')
|
||||
result = json.loads(
|
||||
ProcessUtilities.outputExecutioner(command, self.website.externalApp, True).rstrip('\n'))
|
||||
## Now pack config into same thing
|
||||
|
||||
try:
|
||||
SnapShotID = result['id'] ## snapshot id that we need to store in db
|
||||
files_new = result['summary']['files_new'] ## basically new files in backup
|
||||
total_duration = result['summary']['total_duration'] ## time taken
|
||||
#command = f'chown {self.website.externalApp}:{self.website.externalApp} {self.FinalPathRuctic}/config.json'
|
||||
#ProcessUtilities.executioner(command)
|
||||
|
||||
### Config is saved with each database, snapshot of config is attached to db snapshot with parent
|
||||
|
||||
self.BackupConfig(SnapShotID)
|
||||
|
||||
command = f'chown cyberpanel:cyberpanel {self.FinalPathRuctic}'
|
||||
ProcessUtilities.executioner(command)
|
||||
|
||||
except BaseException as msg:
|
||||
self.UpdateStatus(f'Backup failed as no snapshot id found, error: {str(msg)}',
|
||||
CPBackupsV2.FAILED)
|
||||
return 0
|
||||
|
||||
|
||||
for dbUsers in value:
|
||||
print(f'User: {dbUsers["user"]}, Host: {dbUsers["host"]}, Pass: {dbUsers["password"]}')
|
||||
|
||||
command = f'rm -f {CurrentDBPath}'
|
||||
ProcessUtilities.executioner(command)
|
||||
# command = f'rustic -r {self.repo} backup {CurrentDBPath} --password "" --json 2>/dev/null'
|
||||
# print(f'db command rustic: {command}')
|
||||
# result = json.loads(
|
||||
# ProcessUtilities.outputExecutioner(command, self.website.externalApp, True).rstrip('\n'))
|
||||
#
|
||||
# try:
|
||||
# SnapShotID = result['id'] ## snapshot id that we need to store in db
|
||||
# files_new = result['summary']['files_new'] ## basically new files in backup
|
||||
# total_duration = result['summary']['total_duration'] ## time taken
|
||||
#
|
||||
# self.snapshots.append(SnapShotID)
|
||||
#
|
||||
# ### Config is saved with each database, snapshot of config is attached to db snapshot with parent
|
||||
#
|
||||
# #self.BackupConfig(SnapShotID)
|
||||
#
|
||||
# command = f'chown cyberpanel:cyberpanel {self.FinalPathRuctic}'
|
||||
# ProcessUtilities.executioner(command)
|
||||
#
|
||||
# except BaseException as msg:
|
||||
# self.UpdateStatus(f'Backup failed as no snapshot id found, error: {str(msg)}',
|
||||
# CPBackupsV2.FAILED)
|
||||
# return 0
|
||||
#
|
||||
#
|
||||
# for dbUsers in value:
|
||||
# print(f'User: {dbUsers["user"]}, Host: {dbUsers["host"]}, Pass: {dbUsers["password"]}')
|
||||
#
|
||||
# command = f'rm -f {CurrentDBPath}'
|
||||
# ProcessUtilities.executioner(command)
|
||||
|
||||
else:
|
||||
command = f'rm -f {CurrentDBPath}'
|
||||
@@ -505,6 +559,9 @@ pass = {ObsecurePassword}
|
||||
|
||||
source = f'/home/{self.website.domain}'
|
||||
|
||||
#command = f'chown {self.website.externalApp}:{self.website.externalApp} {self.FinalPathRuctic}/config.json'
|
||||
#ProcessUtilities.executioner(command)
|
||||
|
||||
## Pending add user provided folders in the exclude list
|
||||
|
||||
exclude = f' --exclude-if-present rusticbackup --exclude-if-present logs '
|
||||
@@ -512,14 +569,17 @@ pass = {ObsecurePassword}
|
||||
command = f'rustic -r {self.repo} backup {source} --password "" {exclude} --json 2>/dev/null'
|
||||
result = json.loads(ProcessUtilities.outputExecutioner(command, self.website.externalApp, True).rstrip('\n'))
|
||||
|
||||
|
||||
try:
|
||||
SnapShotID = result['id'] ## snapshot id that we need to store in db
|
||||
files_new = result['summary']['files_new'] ## basically new files in backup
|
||||
total_duration = result['summary']['total_duration'] ## time taken
|
||||
|
||||
self.snapshots.append(SnapShotID)
|
||||
|
||||
### Config is saved with each backup, snapshot of config is attached to data snapshot with parent
|
||||
|
||||
self.BackupConfig(SnapShotID)
|
||||
#self.BackupConfig(SnapShotID)
|
||||
|
||||
except BaseException as msg:
|
||||
self.UpdateStatus(f'Backup failed as no snapshot id found, error: {str(msg)}', CPBackupsV2.FAILED)
|
||||
@@ -541,6 +601,9 @@ pass = {ObsecurePassword}
|
||||
command = f'rustic init -r {self.repo} --password ""'
|
||||
ProcessUtilities.executioner(command, self.website.externalApp)
|
||||
|
||||
#command = f'chown {self.website.externalApp}:{self.website.externalApp} {self.FinalPathRuctic}/config.json'
|
||||
#ProcessUtilities.executioner(command)
|
||||
|
||||
|
||||
source = f'/home/vmail/{self.website.domain}'
|
||||
|
||||
@@ -548,18 +611,20 @@ pass = {ObsecurePassword}
|
||||
|
||||
exclude = f' --exclude-if-present rusticbackup --exclude-if-present logs '
|
||||
|
||||
command = f'rustic -r {self.repo} backup {source} --password "" {exclude} --json 2>/dev/null'
|
||||
command = f'rustic -P /home/{self.website.domain}/.config/rclone/rclone.conf -r {self.repo} backup {source} --password "" {exclude} --json 2>/dev/null'
|
||||
|
||||
result = json.loads(ProcessUtilities.outputExecutioner(command, self.website.externalApp, True).rstrip('\n'))
|
||||
result = json.loads(ProcessUtilities.outputExecutioner(command, None, True).rstrip('\n'))
|
||||
|
||||
try:
|
||||
SnapShotID = result['id'] ## snapshot id that we need to store in db
|
||||
files_new = result['summary']['files_new'] ## basically new files in backup
|
||||
total_duration = result['summary']['total_duration'] ## time taken
|
||||
|
||||
self.snapshots.append(SnapShotID)
|
||||
|
||||
### Config is saved with each email backup, snapshot of config is attached to email snapshot with parent
|
||||
|
||||
self.BackupConfig(SnapShotID)
|
||||
#self.BackupConfig(SnapShotID)
|
||||
|
||||
except BaseException as msg:
|
||||
self.UpdateStatus(f'Backup failed as no snapshot id found, error: {str(msg)}', CPBackupsV2.FAILED)
|
||||
|
||||
@@ -245,7 +245,7 @@ class mysqlUtilities:
|
||||
return str(msg)
|
||||
|
||||
@staticmethod
|
||||
def createDatabaseBackup(databaseName, tempStoragePath):
|
||||
def createDatabaseBackup(databaseName, tempStoragePath, rustic=0, RusticRepoName = None, externalApp = None):
|
||||
try:
|
||||
passFile = "/etc/cyberpanel/mysqlPassword"
|
||||
|
||||
@@ -284,26 +284,55 @@ password=%s
|
||||
|
||||
os.chmod(cnfPath, 0o600)
|
||||
|
||||
command = 'mysqldump --defaults-extra-file=/home/cyberpanel/.my.cnf -u %s --host=%s --port %s %s' % (mysqluser, mysqlhost, mysqlport, databaseName)
|
||||
SHELL = False
|
||||
|
||||
if rustic == 0:
|
||||
|
||||
command = 'mysqldump --defaults-extra-file=/home/cyberpanel/.my.cnf -u %s --host=%s --port %s %s' % (mysqluser, mysqlhost, mysqlport, databaseName)
|
||||
|
||||
if os.path.exists(ProcessUtilities.debugPath):
|
||||
logging.CyberCPLogFileWriter.writeToFile(command)
|
||||
|
||||
cmd = shlex.split(command)
|
||||
|
||||
try:
|
||||
errorPath = '/home/cyberpanel/error-logs.txt'
|
||||
errorLog = open(errorPath, 'a')
|
||||
with open(tempStoragePath + "/" + databaseName + '.sql', 'w') as f:
|
||||
res = subprocess.call(cmd, stdout=f, stderr=errorLog, shell=SHELL)
|
||||
if res != 0:
|
||||
logging.CyberCPLogFileWriter.writeToFile(
|
||||
"Database: " + databaseName + "could not be backed! [createDatabaseBackup]")
|
||||
return 0
|
||||
except subprocess.CalledProcessError as msg:
|
||||
logging.CyberCPLogFileWriter.writeToFile(
|
||||
"Database: " + databaseName + "could not be backed! Error: %s. [createDatabaseBackup]" % (
|
||||
str(msg)))
|
||||
return 0
|
||||
|
||||
else:
|
||||
SHELL = True
|
||||
|
||||
command = f'mysqldump --defaults-extra-file=/home/cyberpanel/.my.cnf -u {mysqluser} --host={mysqlhost} --port {mysqlport} --add-drop-table --allow-keywords --complete-insert --quote-names --skip-comments {databaseName} | sudo -u {externalApp} rustic -r {RusticRepoName} backup --stdin-filename {databaseName}.sql - --password "" --json 2>/dev/null'
|
||||
|
||||
if os.path.exists(ProcessUtilities.debugPath):
|
||||
logging.CyberCPLogFileWriter.writeToFile(command)
|
||||
|
||||
result = json.loads(
|
||||
ProcessUtilities.outputExecutioner(command, None, True).rstrip('\n'))
|
||||
|
||||
try:
|
||||
SnapShotID = result['id'] ## snapshot id that we need to store in db
|
||||
files_new = result['summary']['files_new'] ## basically new files in backup
|
||||
total_duration = result['summary']['total_duration'] ## time taken
|
||||
|
||||
return 1, SnapShotID
|
||||
|
||||
except BaseException as msg:
|
||||
return 0, str(msg)
|
||||
|
||||
if os.path.exists(ProcessUtilities.debugPath):
|
||||
logging.CyberCPLogFileWriter.writeToFile(command)
|
||||
|
||||
cmd = shlex.split(command)
|
||||
|
||||
try:
|
||||
errorPath = '/home/cyberpanel/error-logs.txt'
|
||||
errorLog = open(errorPath, 'a')
|
||||
with open(tempStoragePath+"/"+databaseName+'.sql', 'w') as f:
|
||||
res = subprocess.call(cmd,stdout=f, stderr=errorLog)
|
||||
if res != 0:
|
||||
logging.CyberCPLogFileWriter.writeToFile(
|
||||
"Database: " + databaseName + "could not be backed! [createDatabaseBackup]")
|
||||
return 0
|
||||
except subprocess.CalledProcessError as msg:
|
||||
logging.CyberCPLogFileWriter.writeToFile(
|
||||
"Database: " + databaseName + "could not be backed! Error: %s. [createDatabaseBackup]" % (str(msg)))
|
||||
return 0
|
||||
return 1
|
||||
except BaseException as msg:
|
||||
logging.CyberCPLogFileWriter.writeToFile(str(msg) + "[createDatabaseBackup]")
|
||||
|
||||
@@ -458,6 +458,8 @@ def refreshLicense(request):
|
||||
cpbuv2.SetupRcloneBackend(CPBackupsV2.SFTP, RcloneData)
|
||||
cpbuv2.InitiateBackup()
|
||||
|
||||
|
||||
|
||||
#cpbuv2.InstallRustic()
|
||||
|
||||
final_dic = {'status': 1}
|
||||
|
||||
Reference in New Issue
Block a user