diff --git a/IncBackups/static/IncBackups/IncBackups.js b/IncBackups/static/IncBackups/IncBackups.js index 5d84499b9..892a58fd3 100644 --- a/IncBackups/static/IncBackups/IncBackups.js +++ b/IncBackups/static/IncBackups/IncBackups.js @@ -1241,7 +1241,7 @@ app.controller('restorev2backupoage', function ($scope, $http, $timeout, $compil option.value = 1; - option.text = 'Choose Repooo'; + option.text = 'Choose Repo'; selectBox.appendChild(option); @@ -1478,7 +1478,7 @@ app.controller('CreateV2Backup', function ($scope, $http, $timeout, $compile) { option.value = 1; - option.text = 'Choose Repooo'; + option.text = 'Choose Repo'; selectBox.appendChild(option); diff --git a/IncBackups/templates/IncBackups/CreateV2Backup.html b/IncBackups/templates/IncBackups/CreateV2Backup.html index ac3d7b2f6..d9e8e7699 100644 --- a/IncBackups/templates/IncBackups/CreateV2Backup.html +++ b/IncBackups/templates/IncBackups/CreateV2Backup.html @@ -1,6 +1,6 @@ {% extends "baseTemplate/index.html" %} {% load i18n %} -{% block title %}{% trans "Create V2 Backup" %}{% endblock %} +{% block title %}{% trans "Create v2 Backup" %}{% endblock %} {% block content %} {% load static %} @@ -13,14 +13,14 @@
-

{% trans "Create V2 Backup Site" %} - {% trans "Backup Docs" %}

-

{% trans "This page can be used to create your backup sites" %}

+

{% trans "Create V2 Backup" %} - {% trans "Backup Docs" %}

+

{% trans "This page can be used to create your backup" %}

- {% trans "Create V2 Backup Site" %} + {% trans "Create v2 Backup" %}

@@ -41,7 +41,6 @@
diff --git a/plogical/Backupsv2.py b/plogical/Backupsv2.py index d4cd1c154..40a394d7e 100644 --- a/plogical/Backupsv2.py +++ b/plogical/Backupsv2.py @@ -623,6 +623,242 @@ token = {token} return 1 + #### Resote Functions + + def InitiateRestore(self): + + from websiteFunctions.models import Websites, Backupsv2 + from django.forms.models import model_to_dict + from plogical.mysqlUtilities import mysqlUtilities + self.website = Websites.objects.get(domain=self.data['domain']) + + ## Base path is basically the path set by user where all the backups will be housed + + if not os.path.exists(self.data['BasePath']): + command = f"mkdir -p {self.data['BasePath']}" + ProcessUtilities.executioner(command) + + command = f"chmod 711 {self.data['BasePath']}" + ProcessUtilities.executioner(command) + + self.StartingTimeStamp = CPBackupsV2.FetchCurrentTimeStamp() + + ### Init rustic repo in main func so dont need to do again and again + + while(1): + + self.website = Websites.objects.get(domain=self.data['domain']) + + if self.website.BackupLock == 0: + + Disk1 = f"du -sm /home/{self.website.domain}/" + Disk2 = "2>/dev/null | awk '{print $1}'" + + self.WebsiteDiskUsage = int(ProcessUtilities.outputExecutioner(f"{Disk1} {Disk2}", 'root', True).rstrip('\n')) + + self.CurrentFreeSpaceOnDisk = int(ProcessUtilities.outputExecutioner("df -m / | awk 'NR==2 {print $4}'", 'root', True).rstrip('\n')) + + if self.WebsiteDiskUsage > self.CurrentFreeSpaceOnDisk: + self.UpdateStatus(f'Not enough disk space on the server to backup this website.', CPBackupsV2.FAILED) + return 0 + + ### Before doing anything install rustic + + statusRes, message = self.InstallRustic() + + if statusRes == 0: + self.UpdateStatus(f'Failed to install Rustic, error: {message}', CPBackupsV2.FAILED) + return 0 + + + # = Backupsv2(website=self.website, fileName='backup-' + self.data['domain'] + "-" + time.strftime("%m.%d.%Y_%H-%M-%S"), status=CPBackupsV2.RUNNING, BasePath=self.data['BasePath']) + #self.buv2.save() + + #self.FinalPath = f"{self.data['BasePath']}/{self.buv2.fileName}" + + ### Rustic backup final path + + self.FinalPathRuctic = f"{self.data['BasePath']}/{self.website.domain}" + + + #command = f"mkdir -p {self.FinalPath}" + #ProcessUtilities.executioner(command) + + + + #command = f"chown {website.externalApp}:{website.externalApp} {self.FinalPath}" + #ProcessUtilities.executioner(command) + + #command = f'chown cyberpanel:cyberpanel {self.FinalPath}' + #ProcessUtilities.executioner(command) + + #command = f"chmod 711 {self.FinalPath}" + #ProcessUtilities.executioner(command) + + command = f"mkdir -p {self.FinalPathRuctic}" + ProcessUtilities.executioner(command) + + command = f'chown cyberpanel:cyberpanel {self.FinalPathRuctic}' + ProcessUtilities.executioner(command) + + command = f"chmod 711 {self.FinalPathRuctic}" + ProcessUtilities.executioner(command) + + try: + + self.UpdateStatus('Creating backup config,0', CPBackupsV2.RUNNING) + + Config = {'MainWebsite': model_to_dict(self.website, fields=['domain', 'adminEmail', 'phpSelection', 'state', 'config'])} + Config['admin'] = model_to_dict(self.website.admin, fields=['userName', 'password', 'firstName', 'lastName', + 'email', 'type', 'owner', 'token', 'api', 'securityLevel', + 'state', 'initself.websitesLimit', 'twoFA', 'secretKey', 'config']) + Config['acl'] = model_to_dict(self.website.admin.acl) + + ### Child domains to config + + ChildsList = [] + + for childDomains in self.website.childdomains_set.all(): + print(childDomains.domain) + ChildsList.append(model_to_dict(childDomains)) + + Config['ChildDomains'] = ChildsList + + #print(str(Config)) + + ### Databases + + connection, cursor = mysqlUtilities.setupConnection() + + if connection == 0: + return 0 + + dataBases = self.website.databases_set.all() + DBSList = [] + + for db in dataBases: + + query = f"SELECT host,user FROM mysql.db WHERE db='{db.dbName}';" + cursor.execute(query) + DBUsers = cursor.fetchall() + + UserList = [] + + for databaseUser in DBUsers: + query = f"SELECT password FROM `mysql`.`user` WHERE `Host`='{databaseUser[0]}' AND `User`='{databaseUser[1]}';" + cursor.execute(query) + resp = cursor.fetchall() + print(resp) + UserList.append({'user': databaseUser[1], 'host': databaseUser[0], 'password': resp[0][0]}) + + DBSList.append({db.dbName: UserList}) + + Config['databases'] = DBSList + + WPSitesList = [] + + for wpsite in self.website.wpsites_set.all(): + WPSitesList.append(model_to_dict(wpsite,fields=['title', 'path', 'FinalURL', 'AutoUpdates', 'PluginUpdates', 'ThemeUpdates', 'WPLockState'])) + + Config['WPSites'] = WPSitesList + self.config = Config + + ### DNS Records + + from dns.models import Domains + + self.dnsDomain = Domains.objects.get(name=self.website.domain) + + DNSRecords = [] + + for record in self.dnsDomain.records_set.all(): + DNSRecords.append(model_to_dict(record)) + + Config['MainDNSDomain'] = model_to_dict(self.dnsDomain) + Config['DNSRecords'] = DNSRecords + + ### Email accounts + + try: + from mailServer.models import Domains + + self.emailDomain = Domains.objects.get(domain=self.website.domain) + + EmailAddrList = [] + + for record in self.emailDomain.eusers_set.all(): + EmailAddrList.append(model_to_dict(record)) + + Config['MainEmailDomain'] = model_to_dict(self.emailDomain) + Config['EmailAddresses'] = EmailAddrList + except: + pass + + #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() + + command = f"chmod 600 {self.FinalPathRuctic}/config.json" + ProcessUtilities.executioner(command) + + if self.BackupConfig() == 0: + return 0 + + self.UpdateStatus('Backup config created,5', CPBackupsV2.RUNNING) + except BaseException as msg: + self.UpdateStatus(f'Failed during config generation, Error: {str(msg)}', CPBackupsV2.FAILED) + return 0 + + try: + if self.data['BackupDatabase']: + self.UpdateStatus('Backing up databases..,10', CPBackupsV2.RUNNING) + if self.BackupDataBasesRustic() == 0: + self.UpdateStatus(f'Failed to create backup for databases.', CPBackupsV2.FAILED) + return 0 + + self.UpdateStatus('Database backups completed successfully..,25', CPBackupsV2.RUNNING) + + if self.data['BackupData']: + self.UpdateStatus('Backing up website data..,30', CPBackupsV2.RUNNING) + if self.BackupRustic() == 0: + 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) + + ### 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) + + break + except BaseException as msg: + self.UpdateStatus(f'Failed, Error: {str(msg)}', CPBackupsV2.FAILED) + return 0 + else: + time.sleep(5) + + ### If website lock is there for more then 20 minutes it means old backup is stucked or backup job failed, thus continue backup + + if float(CPBackupsV2.FetchCurrentTimeStamp()) > (float(self.StartingTimeStamp) + 1200): + self.website = Websites.objects.get(domain=self.data['domain']) + self.website.BackupLock = 0 + self.website.save() + # def BackupEmails(self): # # ### This function will backup emails of the website, also need to take care of emails that we need to exclude @@ -744,6 +980,8 @@ token = {token} print('Error: %s'%msg) return 0, str(msg) + + if __name__ == "__main__": try: parser = argparse.ArgumentParser(description='CyberPanel Backup Generator')