initial complete of rustic backups restore

This commit is contained in:
usman@cyberpersons.com
2023-04-03 16:16:01 +05:00
parent a3f1ac3a9c
commit b386a1963c
5 changed files with 73 additions and 208 deletions

View File

@@ -1294,7 +1294,8 @@ app.controller('restorev2backupoage', function ($scope, $http, $timeout, $compil
var data = {
snapshotid: SnapshotId,
path: Path,
selwebsite: $scope.selwebsite
selwebsite: $scope.selwebsite,
selectedrepo:$('#reposelectbox').val()
}
var config = {

View File

@@ -40,6 +40,7 @@
<div class="form-group">
<label class="col-sm-3 control-label">{% trans "Select Repo" %} </label>
<div class="col-sm-6">
<select id="reposelectbox" ng-change="selectrepo()" ng-model="testhabbi" class="form-control">
</select>

View File

@@ -843,6 +843,7 @@ def RestorePathV2(request):
SnapShotId = data['snapshotid']
Path = data['path']
Selectedwebsite = data['selwebsite']
Selectedrepo = data['selectedrepo']
currentACL = ACLManager.loadedACL(userID)
admin = Administrator.objects.get(pk=userID)
@@ -852,25 +853,17 @@ def RestorePathV2(request):
else:
return ACLManager.loadError()
# f'rustic -r testremote snapshots --password "" --json 2>/dev/null'
# final_json = json.dumps({'status': 0, 'fetchStatus': 1, 'error_message': Selectedrepo })
# return HttpResponse(final_json)
vm = CPBackupsV2({'domain': Selectedwebsite, 'BackendName': Selectedrepo, "function": ""})
status, data = vm.FetchSnapShots()
vm = CPBackupsV2({'domain': Selectedwebsite, 'BackendName': Selectedrepo, "function": "", 'BasePath': '/home/backup'})
status = vm.InitiateRestore(SnapShotId, Path)
if status == 1:
final_json = json.dumps({'status': 1, 'fetchStatus': 1, 'error_message': "None", "data": data})
final_json = json.dumps({'status': 1, 'fetchStatus': 1, 'error_message': "None"})
return HttpResponse(final_json)
else:
# final_json = json.dumps({'status': 0, 'fetchStatus': 1, 'error_message': ac,})
final_json = json.dumps({'status': 0, 'fetchStatus': 1, 'error_message': 'Cannot Find!', })
return HttpResponse(final_json)
final_dic = {'status': 1, 'SnapShotId': SnapShotId, 'Path': Path}
final_json = json.dumps(final_dic)
return HttpResponse(final_json)
except BaseException as msg:
final_dic = {'status': 0, 'fetchStatus': 0, 'error_message': str(msg)}
final_json = json.dumps(final_dic)

View File

@@ -60,6 +60,12 @@ class CPBackupsV2(multi.Thread):
##
self.StatusFile = f'/home/cyberpanel/{self.website.domain}_rustic_backup_log'
self.StatusFile_Restore = f'/home/cyberpanel/{self.website.domain}_rustic_backup_log_Restore'
## restore or backup?
self.restore = 0
if os.path.exists(self.StatusFile):
os.remove(self.StatusFile)
@@ -629,7 +635,12 @@ token = {token}
#### Resote Functions
def InitiateRestore(self):
def InitiateRestore(self, snapshotid, path):
### if restore then status file should be restore status file
self.restore = 1
self.StatusFile = self.StatusFile_Restore
from websiteFunctions.models import Websites, Backupsv2
from django.forms.models import model_to_dict
@@ -663,42 +674,14 @@ token = {token}
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)
self.UpdateStatus(f'Not enough disk space on the server to restore 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)
@@ -708,151 +691,29 @@ token = {token}
command = f"chmod 711 {self.FinalPathRuctic}"
ProcessUtilities.executioner(command)
try:
### Find Restore path first, if path is db, only then restore it to cp
self.UpdateStatus('Creating backup config,0', CPBackupsV2.RUNNING)
if path.find('.sql') > -1:
mysqlUtilities.restoreDatabaseBackup(path.rstrip('.sql'), None, None, None, None, 1, self.repo, self.website.externalApp, snapshotid)
else:
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)
if path.find('/home/vmail') > -1:
externalApp = None
else:
externalApp = self.website.externalApp
### Child domains to config
command = f'rustic -r {self.repo} restore {snapshotid}:{path} {path} --password "" --json 2>/dev/null'
result = ProcessUtilities.outputExecutioner(command, externalApp, True)
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()
if os.path.exists(ProcessUtilities.debugPath):
logging.CyberCPLogFileWriter.writeToFile(result)
self.UpdateStatus('Completed', CPBackupsV2.COMPLETED)
break
except BaseException as msg:
self.UpdateStatus(f'Failed, Error: {str(msg)}', CPBackupsV2.FAILED)
return 0
return 1
else:
time.sleep(5)

View File

@@ -339,7 +339,7 @@ password=%s
return 0
@staticmethod
def restoreDatabaseBackup(databaseName, tempStoragePath, dbPassword, passwordCheck = None, additionalName = None):
def restoreDatabaseBackup(databaseName, tempStoragePath, dbPassword, passwordCheck = None, additionalName = None, rustic=0, RusticRepoName = None, externalApp = None, snapshotid = None):
try:
passFile = "/etc/cyberpanel/mysqlPassword"
@@ -379,6 +379,8 @@ password=%s
command = 'chown cyberpanel:cyberpanel %s' % (cnfPath)
subprocess.call(shlex.split(command))
if rustic == 0:
command = 'mysql --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(f'{command} {tempStoragePath}/{databaseName} ' )
@@ -411,6 +413,13 @@ password=%s
connection.close()
return 1
else:
command = f'sudo -u {externalApp} rustic -r {RusticRepoName} dump {snapshotid}:{databaseName}.sql --password "" 2>/dev/null | mysql --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(f'{command} {tempStoragePath}/{databaseName} ')
ProcessUtilities.outputExecutioner(command, None, True)
except BaseException as msg:
logging.CyberCPLogFileWriter.writeToFile(str(msg) + "[restoreDatabaseBackup]")
return 0