2019-12-10 23:04:24 +05:00
|
|
|
#!/usr/local/CyberCP/bin/python
|
2019-10-06 18:41:09 +05:00
|
|
|
import os
|
|
|
|
|
import os.path
|
2021-04-17 23:16:48 -04:00
|
|
|
import shlex
|
|
|
|
|
import subprocess
|
2019-10-06 18:41:09 +05:00
|
|
|
import sys
|
2021-04-18 21:44:54 -04:00
|
|
|
import requests
|
2019-10-06 18:41:09 +05:00
|
|
|
sys.path.append('/usr/local/CyberCP')
|
|
|
|
|
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "CyberCP.settings")
|
|
|
|
|
|
|
|
|
|
import django
|
2019-10-28 12:18:19 +05:00
|
|
|
|
2019-10-06 18:41:09 +05:00
|
|
|
try:
|
|
|
|
|
django.setup()
|
|
|
|
|
except:
|
|
|
|
|
pass
|
|
|
|
|
import threading as multi
|
|
|
|
|
from plogical.processUtilities import ProcessUtilities
|
2019-11-07 16:27:09 +05:00
|
|
|
from .models import IncJob, JobSnapshots
|
2019-10-06 18:41:09 +05:00
|
|
|
from websiteFunctions.models import Websites
|
|
|
|
|
import plogical.randomPassword as randomPassword
|
|
|
|
|
from plogical.CyberCPLogFileWriter import CyberCPLogFileWriter as logging
|
|
|
|
|
import plogical.mysqlUtilities as mysqlUtilities
|
2019-10-28 12:18:19 +05:00
|
|
|
import json
|
|
|
|
|
from django.shortcuts import HttpResponse
|
|
|
|
|
|
2019-10-06 18:41:09 +05:00
|
|
|
try:
|
|
|
|
|
from plogical.virtualHostUtilities import virtualHostUtilities
|
|
|
|
|
from plogical.mailUtilities import mailUtilities
|
|
|
|
|
except:
|
|
|
|
|
pass
|
|
|
|
|
|
2019-10-28 12:18:19 +05:00
|
|
|
|
2019-10-06 18:41:09 +05:00
|
|
|
class IncJobs(multi.Thread):
|
|
|
|
|
|
|
|
|
|
def __init__(self, function, extraArgs):
|
|
|
|
|
multi.Thread.__init__(self)
|
|
|
|
|
self.function = function
|
|
|
|
|
self.extraArgs = extraArgs
|
|
|
|
|
self.repoPath = ''
|
|
|
|
|
self.passwordFile = ''
|
|
|
|
|
self.statusPath = ''
|
|
|
|
|
self.website = ''
|
|
|
|
|
self.backupDestinations = ''
|
|
|
|
|
self.jobid = 0
|
|
|
|
|
self.metaPath = ''
|
2019-11-02 19:29:02 +05:00
|
|
|
self.path = ''
|
|
|
|
|
self.reconstruct = ''
|
2019-10-06 18:41:09 +05:00
|
|
|
|
|
|
|
|
def run(self):
|
|
|
|
|
|
|
|
|
|
if self.function == 'createBackup':
|
|
|
|
|
self.createBackup()
|
|
|
|
|
elif self.function == 'restorePoint':
|
|
|
|
|
self.restorePoint()
|
2019-10-28 12:18:19 +05:00
|
|
|
elif self.function == 'remoteRestore':
|
|
|
|
|
self.restorePoint()
|
|
|
|
|
|
|
|
|
|
def getRemoteBackups(self):
|
2022-04-30 00:28:28 +05:00
|
|
|
if self.backupDestinations[:4] == 'sftp':
|
|
|
|
|
path = '/home/backup/%s' % (self.website)
|
|
|
|
|
command = 'export RESTIC_PASSWORD=%s PATH=${PATH}:/usr/bin && restic -r %s:%s snapshots' % (
|
2019-10-28 12:18:19 +05:00
|
|
|
self.passwordFile, self.backupDestinations, path)
|
2021-11-23 13:39:42 +05:00
|
|
|
return ProcessUtilities.outputExecutioner(command, self.externalApp).split('\n')
|
2019-10-28 12:18:19 +05:00
|
|
|
else:
|
2019-11-02 19:29:02 +05:00
|
|
|
key, secret = self.getAWSData()
|
|
|
|
|
command = 'export RESTIC_PASSWORD=%s AWS_ACCESS_KEY_ID=%s AWS_SECRET_ACCESS_KEY=%s && restic -r s3:s3.amazonaws.com/%s snapshots' % (
|
|
|
|
|
self.passwordFile, key, secret, self.website)
|
2021-11-23 13:39:42 +05:00
|
|
|
return ProcessUtilities.outputExecutioner(command, self.externalApp).split('\n')
|
2019-10-28 12:18:19 +05:00
|
|
|
|
|
|
|
|
def fetchCurrentBackups(self):
|
|
|
|
|
try:
|
|
|
|
|
self.website = self.extraArgs['website']
|
|
|
|
|
self.backupDestinations = self.extraArgs['backupDestinations']
|
|
|
|
|
self.passwordFile = self.extraArgs['password']
|
|
|
|
|
|
2019-11-02 19:29:02 +05:00
|
|
|
result = self.getRemoteBackups()
|
2019-10-28 12:18:19 +05:00
|
|
|
|
|
|
|
|
activator = 0
|
2021-02-03 00:35:08 -05:00
|
|
|
json_data = []
|
2019-11-02 19:29:02 +05:00
|
|
|
if result[0].find('unable to open config file') == -1:
|
|
|
|
|
for items in reversed(result):
|
|
|
|
|
|
|
|
|
|
if items.find('---------------') > -1:
|
|
|
|
|
if activator == 0:
|
|
|
|
|
activator = 1
|
|
|
|
|
continue
|
|
|
|
|
else:
|
|
|
|
|
activator = 0
|
|
|
|
|
|
|
|
|
|
if activator:
|
|
|
|
|
entry = items.split(' ')
|
2021-02-03 00:35:08 -05:00
|
|
|
json_data.append({'id': entry[0],
|
|
|
|
|
'date': "%s %s" % (entry[2], entry[3]),
|
|
|
|
|
'host': entry[5],
|
|
|
|
|
'path': entry[-1]
|
|
|
|
|
})
|
2019-10-28 12:18:19 +05:00
|
|
|
final_json = json.dumps({'status': 1, 'error_message': "None", "data": json_data})
|
|
|
|
|
return HttpResponse(final_json)
|
|
|
|
|
|
2019-12-10 15:09:10 +05:00
|
|
|
except BaseException as msg:
|
2019-10-28 12:18:19 +05:00
|
|
|
logging.writeToFile(str(msg))
|
|
|
|
|
|
2020-04-16 00:06:25 +05:00
|
|
|
## Find restore path
|
|
|
|
|
|
|
|
|
|
def findRestorePath(self):
|
|
|
|
|
|
2020-05-14 14:06:26 +05:00
|
|
|
if ProcessUtilities.decideDistro() == ProcessUtilities.centos or ProcessUtilities.decideDistro() == ProcessUtilities.cent8 \
|
|
|
|
|
or ProcessUtilities.decideDistro() == ProcessUtilities.ubuntu20:
|
2020-04-16 00:06:25 +05:00
|
|
|
self.restoreTarget = '/'
|
|
|
|
|
return 1
|
|
|
|
|
else:
|
|
|
|
|
if self.jobid.type[:8] == 'database':
|
2021-11-23 19:20:11 +05:00
|
|
|
self.restoreTarget = '/usr/local/CyberCP/tmp/'
|
2020-04-16 00:06:25 +05:00
|
|
|
elif self.jobid.type[:4] == 'data':
|
|
|
|
|
self.restoreTarget = '/home/'
|
|
|
|
|
elif self.jobid.type[:5] == 'email':
|
|
|
|
|
self.restoreTarget = '/home/vmail/'
|
|
|
|
|
elif self.jobid.type[:4] == 'meta':
|
|
|
|
|
self.restoreTarget = '/home/%s/' % (self.website)
|
|
|
|
|
|
2019-10-28 12:18:19 +05:00
|
|
|
####
|
2019-10-06 18:41:09 +05:00
|
|
|
|
2019-10-14 17:40:58 +05:00
|
|
|
def getAWSData(self):
|
|
|
|
|
key = self.backupDestinations.split('/')[-1]
|
|
|
|
|
path = '/home/cyberpanel/aws/%s' % (key)
|
|
|
|
|
secret = open(path, 'r').read()
|
|
|
|
|
return key, secret
|
|
|
|
|
|
2021-05-07 22:22:29 +05:00
|
|
|
## Last argument delete is set when the snapshot is to be deleted from this repo, when this argument is set, any preceding argument is not used
|
|
|
|
|
|
|
|
|
|
def awsFunction(self, fType, backupPath=None, snapshotID=None, bType=None, delete=None):
|
2019-10-14 17:40:58 +05:00
|
|
|
try:
|
|
|
|
|
if fType == 'backup':
|
|
|
|
|
key, secret = self.getAWSData()
|
2020-01-23 22:51:38 +05:00
|
|
|
|
2021-04-17 21:40:16 -04:00
|
|
|
# Define our excludes file for use with restic
|
|
|
|
|
backupExcludesFile = '/home/%s/backup-exclude.conf' % (self.website.domain)
|
|
|
|
|
resticBackupExcludeCMD = ' --exclude-file=%s' % (backupExcludesFile)
|
|
|
|
|
|
2021-05-09 17:55:05 +05:00
|
|
|
command = 'export AWS_ACCESS_KEY_ID=%s AWS_SECRET_ACCESS_KEY=%s && restic -r s3:s3.amazonaws.com/%s backup %s --password-file %s --exclude /home/%s/backup --exclude /home/%s/incbackup' % (
|
|
|
|
|
key, secret, self.website.domain, backupPath, self.passwordFile, self.website.domain, self.website.domain)
|
2020-01-23 22:51:38 +05:00
|
|
|
|
2021-04-17 21:40:16 -04:00
|
|
|
# If /home/%s/backup-exclude.conf file exists lets pass this to restic by appending the command to end.
|
|
|
|
|
if os.path.isfile(backupExcludesFile):
|
|
|
|
|
command = command + resticBackupExcludeCMD
|
2021-11-23 13:39:42 +05:00
|
|
|
result = ProcessUtilities.outputExecutioner(command, self.externalApp)
|
2020-01-23 20:53:17 +05:00
|
|
|
|
|
|
|
|
if result.find('saved') == -1:
|
|
|
|
|
logging.statusWriter(self.statusPath, '%s. [5009].' % (result), 1)
|
|
|
|
|
return 0
|
|
|
|
|
|
2019-10-14 17:40:58 +05:00
|
|
|
snapShotid = result.split(' ')[-2]
|
2020-01-23 22:51:38 +05:00
|
|
|
|
2019-10-14 17:40:58 +05:00
|
|
|
if bType == 'database':
|
2019-10-28 12:18:19 +05:00
|
|
|
newSnapshot = JobSnapshots(job=self.jobid,
|
2019-12-21 19:34:11 +05:00
|
|
|
type='%s:%s' % (bType, backupPath.split('/')[-1].rstrip('.sql')),
|
2019-10-14 17:40:58 +05:00
|
|
|
snapshotid=snapShotid,
|
|
|
|
|
destination=self.backupDestinations)
|
|
|
|
|
else:
|
2019-10-28 12:18:19 +05:00
|
|
|
newSnapshot = JobSnapshots(job=self.jobid, type='%s:%s' % (bType, backupPath),
|
|
|
|
|
snapshotid=snapShotid,
|
|
|
|
|
destination=self.backupDestinations)
|
2019-10-14 17:40:58 +05:00
|
|
|
newSnapshot.save()
|
2020-01-23 22:51:38 +05:00
|
|
|
return 1
|
2019-10-14 17:40:58 +05:00
|
|
|
else:
|
2019-11-02 19:29:02 +05:00
|
|
|
if self.reconstruct == 'remote':
|
|
|
|
|
self.backupDestinations = self.backupDestinations
|
2020-01-23 22:51:38 +05:00
|
|
|
|
2019-11-02 19:29:02 +05:00
|
|
|
key, secret = self.getAWSData()
|
2020-01-23 22:51:38 +05:00
|
|
|
|
2020-04-16 00:06:25 +05:00
|
|
|
command = 'export RESTIC_PASSWORD=%s AWS_ACCESS_KEY_ID=%s AWS_SECRET_ACCESS_KEY=%s && restic -r s3:s3.amazonaws.com/%s restore %s --target %s' % (
|
2019-11-02 19:29:02 +05:00
|
|
|
self.passwordFile,
|
2020-04-16 00:06:25 +05:00
|
|
|
key, secret, self.website, snapshotID, self.restoreTarget)
|
2020-01-23 22:51:38 +05:00
|
|
|
|
2021-11-23 13:39:42 +05:00
|
|
|
result = ProcessUtilities.outputExecutioner(command, self.externalApp)
|
2020-01-23 22:51:38 +05:00
|
|
|
|
|
|
|
|
if result.find('restoring') == -1:
|
|
|
|
|
logging.statusWriter(self.statusPath, 'Failed: %s. [5009]' % (result), 1)
|
|
|
|
|
return 0
|
2021-05-07 22:22:29 +05:00
|
|
|
elif delete:
|
|
|
|
|
|
|
|
|
|
self.backupDestinations = self.jobid.destination
|
|
|
|
|
|
|
|
|
|
key, secret = self.getAWSData()
|
|
|
|
|
|
2022-04-30 00:28:28 +05:00
|
|
|
command = 'export AWS_ACCESS_KEY_ID=%s AWS_SECRET_ACCESS_KEY=%s && restic -r s3:s3.amazonaws.com/%s forget %s --password-file %s' % (
|
|
|
|
|
key, secret, self.website, snapshotID, self.passwordFile)
|
2021-05-07 22:22:29 +05:00
|
|
|
|
2021-11-23 13:39:42 +05:00
|
|
|
result = ProcessUtilities.outputExecutioner(command, self.externalApp)
|
2021-05-07 22:22:29 +05:00
|
|
|
|
2021-05-09 13:48:15 +05:00
|
|
|
if result.find('removed snapshot') > -1 or result.find('deleted') > -1:
|
|
|
|
|
pass
|
|
|
|
|
else:
|
2021-05-07 22:22:29 +05:00
|
|
|
logging.statusWriter(self.statusPath, 'Failed: %s. [5009]' % (result), 1)
|
|
|
|
|
return 0
|
2022-04-30 00:28:28 +05:00
|
|
|
|
|
|
|
|
command = 'export AWS_ACCESS_KEY_ID=%s AWS_SECRET_ACCESS_KEY=%s && restic -r s3:s3.amazonaws.com/%s prune --password-file %s' % (
|
|
|
|
|
key, secret, self.website, self.passwordFile)
|
|
|
|
|
|
|
|
|
|
ProcessUtilities.outputExecutioner(command, self.externalApp)
|
2019-11-02 19:29:02 +05:00
|
|
|
else:
|
|
|
|
|
self.backupDestinations = self.jobid.destination
|
2020-01-23 22:51:38 +05:00
|
|
|
|
2019-11-02 19:29:02 +05:00
|
|
|
key, secret = self.getAWSData()
|
2020-01-23 22:51:38 +05:00
|
|
|
|
2020-04-16 00:06:25 +05:00
|
|
|
command = 'export AWS_ACCESS_KEY_ID=%s AWS_SECRET_ACCESS_KEY=%s && restic -r s3:s3.amazonaws.com/%s restore %s --password-file %s --target %s' % (
|
|
|
|
|
key, secret, self.website, snapshotID, self.passwordFile, self.restoreTarget)
|
2020-01-23 22:51:38 +05:00
|
|
|
|
2021-11-23 13:39:42 +05:00
|
|
|
result = ProcessUtilities.outputExecutioner(command, self.externalApp)
|
2020-01-23 22:51:38 +05:00
|
|
|
|
|
|
|
|
if result.find('restoring') == -1:
|
|
|
|
|
logging.statusWriter(self.statusPath, 'Failed: %s. [5009]' % (result), 1)
|
|
|
|
|
return 0
|
|
|
|
|
|
|
|
|
|
return 1
|
2019-12-10 15:09:10 +05:00
|
|
|
except BaseException as msg:
|
2019-10-15 22:59:22 +05:00
|
|
|
logging.statusWriter(self.statusPath, "%s [88][5009]" % (str(msg)), 1)
|
2019-10-14 17:40:58 +05:00
|
|
|
return 0
|
|
|
|
|
|
2021-05-07 22:22:29 +05:00
|
|
|
## Last argument delete is set when the snapshot is to be deleted from this repo, when this argument is set, any preceding argument is not used
|
|
|
|
|
|
|
|
|
|
def localFunction(self, backupPath, type, restore=None, delete=None):
|
|
|
|
|
|
2019-10-15 22:59:22 +05:00
|
|
|
if restore == None:
|
2021-04-17 21:40:16 -04:00
|
|
|
# Define our excludes file for use with restic
|
|
|
|
|
backupExcludesFile = '/home/%s/backup-exclude.conf' % (self.website.domain)
|
|
|
|
|
resticBackupExcludeCMD = ' --exclude-file=%s' % (backupExcludesFile)
|
|
|
|
|
|
2021-05-09 17:55:05 +05:00
|
|
|
command = 'restic -r %s backup %s --password-file %s --exclude %s --exclude /home/%s/backup' % (
|
|
|
|
|
self.repoPath, backupPath, self.passwordFile, self.repoPath, self.website.domain)
|
2021-04-17 21:40:16 -04:00
|
|
|
# If /home/%s/backup-exclude.conf file exists lets pass this to restic by appending the command to end.
|
|
|
|
|
if os.path.isfile(backupExcludesFile):
|
|
|
|
|
command = command + resticBackupExcludeCMD
|
2021-11-23 13:39:42 +05:00
|
|
|
result = ProcessUtilities.outputExecutioner(command, self.externalApp)
|
2020-01-23 20:53:17 +05:00
|
|
|
|
|
|
|
|
if result.find('saved') == -1:
|
|
|
|
|
logging.statusWriter(self.statusPath, '%s. [5009].' % (result), 1)
|
|
|
|
|
return 0
|
|
|
|
|
|
2019-10-15 22:59:22 +05:00
|
|
|
snapShotid = result.split(' ')[-2]
|
|
|
|
|
|
|
|
|
|
if type == 'database':
|
|
|
|
|
newSnapshot = JobSnapshots(job=self.jobid,
|
2019-12-21 19:34:11 +05:00
|
|
|
type='%s:%s' % (type, backupPath.split('/')[-1].rstrip('.sql')),
|
2019-10-15 22:59:22 +05:00
|
|
|
snapshotid=snapShotid,
|
|
|
|
|
destination=self.backupDestinations)
|
|
|
|
|
else:
|
|
|
|
|
newSnapshot = JobSnapshots(job=self.jobid, type='%s:%s' % (type, backupPath), snapshotid=snapShotid,
|
|
|
|
|
destination=self.backupDestinations)
|
|
|
|
|
newSnapshot.save()
|
2021-05-07 22:22:29 +05:00
|
|
|
return 1
|
|
|
|
|
elif delete:
|
|
|
|
|
|
|
|
|
|
repoLocation = '/home/%s/incbackup' % (self.website)
|
|
|
|
|
|
2022-04-30 00:28:28 +05:00
|
|
|
command = 'restic -r %s forget %s --password-file %s' % (repoLocation, self.jobid.snapshotid, self.passwordFile)
|
2021-11-23 13:39:42 +05:00
|
|
|
result = ProcessUtilities.outputExecutioner(command, self.externalApp)
|
2021-05-07 22:22:29 +05:00
|
|
|
|
2021-05-09 13:48:15 +05:00
|
|
|
if result.find('removed snapshot') > -1 or result.find('deleted') > -1:
|
|
|
|
|
pass
|
|
|
|
|
else:
|
2021-05-07 22:22:29 +05:00
|
|
|
logging.statusWriter(self.statusPath, 'Failed: %s. [5009]' % (result), 1)
|
|
|
|
|
return 0
|
|
|
|
|
|
2022-04-30 00:28:28 +05:00
|
|
|
command = 'restic -r %s prune --password-file %s' % (repoLocation, self.passwordFile)
|
|
|
|
|
ProcessUtilities.outputExecutioner(command, self.externalApp)
|
|
|
|
|
|
2020-01-23 22:51:38 +05:00
|
|
|
return 1
|
2019-10-15 22:59:22 +05:00
|
|
|
else:
|
|
|
|
|
repoLocation = '/home/%s/incbackup' % (self.website)
|
2020-04-16 00:06:25 +05:00
|
|
|
command = 'restic -r %s restore %s --target %s --password-file %s' % (
|
|
|
|
|
repoLocation, self.jobid.snapshotid, self.restoreTarget, self.passwordFile)
|
2020-01-23 22:51:38 +05:00
|
|
|
|
2021-11-23 13:39:42 +05:00
|
|
|
result = ProcessUtilities.outputExecutioner(command, self.externalApp)
|
2019-10-15 22:59:22 +05:00
|
|
|
|
2020-01-23 22:51:38 +05:00
|
|
|
if result.find('restoring') == -1:
|
|
|
|
|
logging.statusWriter(self.statusPath, 'Failed: %s. [5009]' % (result), 1)
|
|
|
|
|
return 0
|
2020-01-23 20:53:17 +05:00
|
|
|
|
2020-01-23 22:51:38 +05:00
|
|
|
return 1
|
2020-01-23 20:53:17 +05:00
|
|
|
|
2021-05-07 22:22:29 +05:00
|
|
|
## Last argument delete is set when the snapshot is to be deleted from this repo, when this argument is set, any preceding argument is not used
|
|
|
|
|
|
|
|
|
|
def sftpFunction(self, backupPath, type, restore=None, delete=None):
|
2022-04-30 00:28:28 +05:00
|
|
|
return 0
|
2019-10-15 22:59:22 +05:00
|
|
|
if restore == None:
|
2021-04-17 21:40:16 -04:00
|
|
|
# Define our excludes file for use with restic
|
|
|
|
|
backupExcludesFile = '/home/%s/backup-exclude.conf' % (self.website.domain)
|
|
|
|
|
resticBackupExcludeCMD = ' --exclude-file=%s' % (backupExcludesFile)
|
2022-04-30 00:28:28 +05:00
|
|
|
remotePath = '/home/backup/%s' % (self.website.domain)
|
|
|
|
|
command = 'export PATH=${PATH}:/usr/bin && restic -r %s:%s backup %s --password-file %s --exclude %s --exclude /home/%s/backup' % (
|
2021-05-09 17:55:05 +05:00
|
|
|
self.backupDestinations, remotePath, backupPath, self.passwordFile, self.repoPath, self.website.domain)
|
2021-04-17 21:40:16 -04:00
|
|
|
# If /home/%s/backup-exclude.conf file exists lets pass this to restic by appending the command to end.
|
|
|
|
|
if os.path.isfile(backupExcludesFile):
|
2022-04-30 00:28:28 +05:00
|
|
|
command = command + resticBackupExcludeCMD
|
2021-11-23 13:39:42 +05:00
|
|
|
result = ProcessUtilities.outputExecutioner(command, self.externalApp)
|
2020-01-23 20:53:17 +05:00
|
|
|
|
|
|
|
|
if result.find('saved') == -1:
|
|
|
|
|
logging.statusWriter(self.statusPath, '%s. [5009].' % (result), 1)
|
|
|
|
|
return 0
|
|
|
|
|
|
2019-10-15 22:59:22 +05:00
|
|
|
snapShotid = result.split(' ')[-2]
|
|
|
|
|
|
|
|
|
|
if type == 'database':
|
|
|
|
|
newSnapshot = JobSnapshots(job=self.jobid,
|
2019-12-21 19:34:11 +05:00
|
|
|
type='%s:%s' % (type, backupPath.split('/')[-1].rstrip('.sql')),
|
2019-10-15 22:59:22 +05:00
|
|
|
snapshotid=snapShotid,
|
|
|
|
|
destination=self.backupDestinations)
|
|
|
|
|
else:
|
|
|
|
|
newSnapshot = JobSnapshots(job=self.jobid, type='%s:%s' % (type, backupPath), snapshotid=snapShotid,
|
|
|
|
|
destination=self.backupDestinations)
|
|
|
|
|
newSnapshot.save()
|
2020-01-23 22:51:38 +05:00
|
|
|
return 1
|
2021-05-07 22:22:29 +05:00
|
|
|
elif delete:
|
2022-04-30 00:28:28 +05:00
|
|
|
repoLocation = '/home/backup/%s' % (self.website)
|
|
|
|
|
command = 'export PATH=${PATH}:/usr/bin && restic -r %s:%s forget %s --password-file %s' % (
|
|
|
|
|
self.jobid.destination, repoLocation, self.jobid.snapshotid, self.passwordFile)
|
2021-11-23 13:39:42 +05:00
|
|
|
result = ProcessUtilities.outputExecutioner(command, self.externalApp)
|
2021-05-09 13:48:15 +05:00
|
|
|
|
|
|
|
|
if result.find('removed snapshot') > -1 or result.find('deleted') > -1:
|
|
|
|
|
pass
|
|
|
|
|
else:
|
2021-05-07 22:22:29 +05:00
|
|
|
logging.statusWriter(self.statusPath, 'Failed: %s. [5009]' % (result), 1)
|
|
|
|
|
return 0
|
2022-04-30 00:28:28 +05:00
|
|
|
|
|
|
|
|
command = 'export PATH=${PATH}:/usr/bin && restic -r %s:%s prune --password-file %s' % (self.jobid.destination, repoLocation, self.passwordFile)
|
|
|
|
|
ProcessUtilities.outputExecutioner(command, self.externalApp)
|
2019-10-15 22:59:22 +05:00
|
|
|
else:
|
2019-11-02 19:29:02 +05:00
|
|
|
if self.reconstruct == 'remote':
|
2022-04-30 00:28:28 +05:00
|
|
|
repoLocation = '/home/backup/%s' % (self.website)
|
|
|
|
|
command = 'export RESTIC_PASSWORD=%s PATH=${PATH}:/usr/bin && restic -r %s:%s restore %s --target %s' % (
|
2019-11-02 19:29:02 +05:00
|
|
|
self.passwordFile,
|
2020-04-16 00:06:25 +05:00
|
|
|
self.backupDestinations, repoLocation, self.jobid, self.restoreTarget)
|
2021-11-23 13:39:42 +05:00
|
|
|
result = ProcessUtilities.outputExecutioner(command, self.externalApp)
|
2020-01-23 22:51:38 +05:00
|
|
|
if result.find('restoring') == -1:
|
|
|
|
|
logging.statusWriter(self.statusPath, 'Failed: %s. [5009]' % (result), 1)
|
|
|
|
|
return 0
|
2019-11-02 19:29:02 +05:00
|
|
|
else:
|
2022-04-30 00:28:28 +05:00
|
|
|
repoLocation = '/home/backup/%s' % (self.website)
|
|
|
|
|
command = 'export PATH=${PATH}:/usr/bin && restic -r %s:%s restore %s --target %s --password-file %s' % (
|
2020-04-16 00:06:25 +05:00
|
|
|
self.jobid.destination, repoLocation, self.jobid.snapshotid, self.restoreTarget, self.passwordFile)
|
2021-11-23 13:39:42 +05:00
|
|
|
result = ProcessUtilities.outputExecutioner(command, self.externalApp)
|
2020-01-23 22:51:38 +05:00
|
|
|
if result.find('restoring') == -1:
|
|
|
|
|
logging.statusWriter(self.statusPath, 'Failed: %s. [5009]' % (result), 1)
|
|
|
|
|
return 0
|
|
|
|
|
|
|
|
|
|
return 1
|
2019-10-15 22:59:22 +05:00
|
|
|
|
2019-10-06 18:41:09 +05:00
|
|
|
def restoreData(self):
|
|
|
|
|
try:
|
|
|
|
|
|
2019-11-02 19:29:02 +05:00
|
|
|
if self.reconstruct == 'remote':
|
2022-04-30 00:28:28 +05:00
|
|
|
if self.backupDestinations[:4] == 'sftp':
|
2019-11-02 19:29:02 +05:00
|
|
|
self.sftpFunction('none', 'none', 1)
|
|
|
|
|
else:
|
2020-01-23 22:51:38 +05:00
|
|
|
if self.awsFunction('restore', '', self.jobid) == 0:
|
|
|
|
|
return 0
|
2019-10-14 17:40:58 +05:00
|
|
|
else:
|
2019-11-02 19:29:02 +05:00
|
|
|
if self.jobid.destination == 'local':
|
2020-01-23 22:51:38 +05:00
|
|
|
return self.localFunction('none', 'none', 1)
|
2022-04-30 00:28:28 +05:00
|
|
|
elif self.jobid.destination[:4] == 'sftp':
|
2020-01-23 22:51:38 +05:00
|
|
|
return self.sftpFunction('none', 'none', 1)
|
2019-11-02 19:29:02 +05:00
|
|
|
else:
|
2020-01-23 22:51:38 +05:00
|
|
|
return self.awsFunction('restore', '', self.jobid.snapshotid)
|
2019-10-06 18:41:09 +05:00
|
|
|
|
2020-01-23 23:20:06 +05:00
|
|
|
return 1
|
|
|
|
|
|
2019-12-10 15:09:10 +05:00
|
|
|
except BaseException as msg:
|
2019-10-15 22:59:22 +05:00
|
|
|
logging.statusWriter(self.statusPath, "%s [138][5009]" % (str(msg)), 1)
|
2019-10-06 18:41:09 +05:00
|
|
|
return 0
|
|
|
|
|
|
|
|
|
|
def restoreDatabase(self):
|
|
|
|
|
try:
|
|
|
|
|
|
2019-11-02 19:29:02 +05:00
|
|
|
if self.reconstruct == 'remote':
|
2022-04-30 00:28:28 +05:00
|
|
|
if self.backupDestinations[:4] == 'sftp':
|
2020-01-23 22:51:38 +05:00
|
|
|
if self.sftpFunction('none', 'none', 1) == 0:
|
|
|
|
|
return 0
|
2019-11-02 19:29:02 +05:00
|
|
|
else:
|
2020-01-23 22:51:38 +05:00
|
|
|
if self.awsFunction('restore', '', self.jobid) == 0:
|
|
|
|
|
return 0
|
|
|
|
|
|
|
|
|
|
## Restore proper permissions
|
|
|
|
|
|
|
|
|
|
command = 'chown cyberpanel:cyberpanel /home/cyberpanel'
|
|
|
|
|
ProcessUtilities.executioner(command)
|
|
|
|
|
|
|
|
|
|
command = 'chmod 755 /home/cyberpanel'
|
|
|
|
|
ProcessUtilities.executioner(command)
|
|
|
|
|
|
|
|
|
|
##
|
2019-11-02 19:29:02 +05:00
|
|
|
|
|
|
|
|
if mysqlUtilities.mysqlUtilities.restoreDatabaseBackup(self.path.split('/')[-1].rstrip('.sql'),
|
2021-11-23 19:20:11 +05:00
|
|
|
'/usr/local/CyberCP/tmp', 'dummy', 'dummy') == 0:
|
2019-11-02 19:29:02 +05:00
|
|
|
raise BaseException
|
2019-10-14 17:40:58 +05:00
|
|
|
else:
|
2019-10-06 18:41:09 +05:00
|
|
|
|
2019-11-02 19:29:02 +05:00
|
|
|
if self.jobid.destination == 'local':
|
2020-01-23 22:51:38 +05:00
|
|
|
if self.localFunction('none', 'none', 1) == 0:
|
|
|
|
|
return 0
|
2022-04-30 00:28:28 +05:00
|
|
|
elif self.jobid.destination[:4] == 'sftp':
|
2020-01-23 22:51:38 +05:00
|
|
|
if self.sftpFunction('none', 'none', 1) == 0:
|
|
|
|
|
return 0
|
2019-11-02 19:29:02 +05:00
|
|
|
else:
|
2020-01-23 22:51:38 +05:00
|
|
|
if self.awsFunction('restore', '', self.jobid.snapshotid) == 0:
|
|
|
|
|
return 0
|
2019-11-02 19:29:02 +05:00
|
|
|
|
2021-11-23 19:20:11 +05:00
|
|
|
|
2019-11-02 19:29:02 +05:00
|
|
|
if mysqlUtilities.mysqlUtilities.restoreDatabaseBackup(self.jobid.type.split(':')[1].rstrip('.sql'),
|
2021-11-23 19:20:11 +05:00
|
|
|
'/home/%s' % (self.website), 'dummy', 'dummy') == 0:
|
2019-12-21 19:34:11 +05:00
|
|
|
raise BaseException('Can not restore database backup.')
|
2019-10-06 18:41:09 +05:00
|
|
|
|
|
|
|
|
try:
|
2019-11-02 19:29:02 +05:00
|
|
|
if self.reconstruct == 'remote':
|
2021-11-23 19:20:11 +05:00
|
|
|
os.remove('/usr/local/CyberCP/tmp/%s' % (self.path.split('/')[-1]))
|
2019-11-02 19:29:02 +05:00
|
|
|
else:
|
2021-11-23 19:20:11 +05:00
|
|
|
os.remove('/usr/local/CyberCP/tmp/%s.sql' % (self.jobid.type.split(':')[1]))
|
|
|
|
|
os.remove('/home/%s/%s.sql' % (self.website.domain, self.jobid.type.split(':')[1]))
|
2019-12-10 15:09:10 +05:00
|
|
|
except BaseException as msg:
|
2019-10-15 22:59:22 +05:00
|
|
|
logging.writeToFile(str(msg))
|
2019-10-06 18:41:09 +05:00
|
|
|
|
2020-01-23 22:51:38 +05:00
|
|
|
return 1
|
|
|
|
|
|
2019-12-10 15:09:10 +05:00
|
|
|
except BaseException as msg:
|
2019-10-15 22:59:22 +05:00
|
|
|
logging.statusWriter(self.statusPath, "%s [160][5009]" % (str(msg)), 1)
|
2019-10-06 18:41:09 +05:00
|
|
|
return 0
|
|
|
|
|
|
|
|
|
|
def restoreEmail(self):
|
|
|
|
|
try:
|
|
|
|
|
|
2019-11-02 19:29:02 +05:00
|
|
|
if self.reconstruct == 'remote':
|
2022-04-30 00:28:28 +05:00
|
|
|
if self.backupDestinations[:4] == 'sftp':
|
2020-01-23 22:51:38 +05:00
|
|
|
if self.sftpFunction('none', 'none', 1) == 0:
|
|
|
|
|
return 0
|
2019-11-02 19:29:02 +05:00
|
|
|
else:
|
2020-01-23 22:51:38 +05:00
|
|
|
if self.awsFunction('restore', '', self.jobid) == 0:
|
|
|
|
|
return 0
|
2019-10-14 17:40:58 +05:00
|
|
|
else:
|
2019-11-02 19:29:02 +05:00
|
|
|
if self.jobid.destination == 'local':
|
2020-01-23 22:51:38 +05:00
|
|
|
return self.localFunction('none', 'none', 1)
|
2022-04-30 00:28:28 +05:00
|
|
|
elif self.jobid.destination[:4] == 'sftp':
|
2020-01-23 22:51:38 +05:00
|
|
|
return self.sftpFunction('none', 'none', 1)
|
2019-11-02 19:29:02 +05:00
|
|
|
else:
|
2020-01-23 22:51:38 +05:00
|
|
|
return self.awsFunction('restore', '', self.jobid.snapshotid)
|
2019-10-06 18:41:09 +05:00
|
|
|
|
2020-01-23 23:20:06 +05:00
|
|
|
return 1
|
|
|
|
|
|
2019-12-10 15:09:10 +05:00
|
|
|
except BaseException as msg:
|
2019-10-06 18:41:09 +05:00
|
|
|
logging.statusWriter(self.statusPath, "%s [46][5009]" % (str(msg)), 1)
|
|
|
|
|
return 0
|
|
|
|
|
|
2019-10-15 22:59:22 +05:00
|
|
|
def reconstructWithMeta(self):
|
|
|
|
|
try:
|
|
|
|
|
|
2019-11-02 19:29:02 +05:00
|
|
|
if self.reconstruct == 'remote':
|
2022-04-30 00:28:28 +05:00
|
|
|
if self.backupDestinations[:4] == 'sftp':
|
2020-01-23 22:51:38 +05:00
|
|
|
if self.sftpFunction('none', 'none', 1) == 0:
|
|
|
|
|
return 0
|
2019-11-02 19:29:02 +05:00
|
|
|
else:
|
2020-01-23 22:51:38 +05:00
|
|
|
if self.awsFunction('restore', '', self.jobid) == 0:
|
|
|
|
|
return 0
|
2019-10-15 22:59:22 +05:00
|
|
|
else:
|
2019-11-02 19:29:02 +05:00
|
|
|
if self.jobid.destination == 'local':
|
2020-01-23 22:51:38 +05:00
|
|
|
if self.localFunction('none', 'none', 1) == 0:
|
|
|
|
|
return 0
|
2022-04-30 00:28:28 +05:00
|
|
|
elif self.jobid.destination[:4] == 'sftp':
|
2020-01-23 22:51:38 +05:00
|
|
|
if self.sftpFunction('none', 'none', 1) == 0:
|
|
|
|
|
return 0
|
2019-11-02 19:29:02 +05:00
|
|
|
else:
|
2020-01-23 22:51:38 +05:00
|
|
|
if self.awsFunction('restore', '', self.jobid.snapshotid) == 0:
|
|
|
|
|
return 0
|
2019-10-15 22:59:22 +05:00
|
|
|
|
|
|
|
|
metaPathNew = '/home/%s/meta.xml' % (self.website)
|
2019-12-21 19:34:11 +05:00
|
|
|
execPath = "nice -n 10 /usr/local/CyberCP/bin/python " + virtualHostUtilities.cyberPanel + "/plogical/restoreMeta.py"
|
2019-10-15 22:59:22 +05:00
|
|
|
execPath = execPath + " submitRestore --metaPath %s --statusFile %s" % (metaPathNew, self.statusPath)
|
|
|
|
|
result = ProcessUtilities.outputExecutioner(execPath)
|
|
|
|
|
logging.statusWriter(self.statusPath, result, 1)
|
|
|
|
|
|
2019-11-02 19:29:02 +05:00
|
|
|
try:
|
|
|
|
|
os.remove(metaPathNew)
|
|
|
|
|
except:
|
|
|
|
|
pass
|
|
|
|
|
|
2020-01-23 23:20:06 +05:00
|
|
|
return 1
|
2019-12-10 15:09:10 +05:00
|
|
|
except BaseException as msg:
|
2019-10-15 22:59:22 +05:00
|
|
|
logging.statusWriter(self.statusPath, "%s [46][5009]" % (str(msg)), 1)
|
|
|
|
|
return 0
|
|
|
|
|
|
2019-10-06 18:41:09 +05:00
|
|
|
def restorePoint(self):
|
|
|
|
|
try:
|
2021-05-07 22:22:29 +05:00
|
|
|
|
2019-10-06 18:41:09 +05:00
|
|
|
self.statusPath = self.extraArgs['tempPath']
|
|
|
|
|
self.website = self.extraArgs['website']
|
|
|
|
|
jobid = self.extraArgs['jobid']
|
2019-11-02 19:29:02 +05:00
|
|
|
self.reconstruct = self.extraArgs['reconstruct']
|
|
|
|
|
|
2021-11-23 13:39:42 +05:00
|
|
|
WebsiteObject = Websites.objects.get(domain=self.website)
|
|
|
|
|
|
|
|
|
|
self.externalApp = WebsiteObject.externalApp
|
|
|
|
|
|
2019-11-02 19:29:02 +05:00
|
|
|
if self.reconstruct == 'remote':
|
2020-07-28 22:33:08 +05:00
|
|
|
|
|
|
|
|
self.findRestorePath()
|
|
|
|
|
|
2019-11-02 19:29:02 +05:00
|
|
|
self.jobid = self.extraArgs['jobid']
|
|
|
|
|
self.backupDestinations = self.extraArgs['backupDestinations']
|
|
|
|
|
self.passwordFile = self.extraArgs['password']
|
|
|
|
|
self.path = self.extraArgs['path']
|
|
|
|
|
|
|
|
|
|
if self.path.find('.sql') > -1:
|
|
|
|
|
message = 'Restoring database..'
|
|
|
|
|
logging.statusWriter(self.statusPath, message, 1)
|
2020-01-23 23:20:06 +05:00
|
|
|
if self.restoreDatabase() == 0:
|
|
|
|
|
return 0
|
2019-11-02 19:29:02 +05:00
|
|
|
message = 'Database restored.'
|
|
|
|
|
logging.statusWriter(self.statusPath, message, 1)
|
|
|
|
|
elif self.path == '/home/%s' % (self.website):
|
|
|
|
|
message = 'Restoring data..'
|
|
|
|
|
logging.statusWriter(self.statusPath, message, 1)
|
2020-01-23 23:20:06 +05:00
|
|
|
if self.restoreData() == 0:
|
|
|
|
|
return 0
|
2019-11-02 19:29:02 +05:00
|
|
|
message = 'Data restored..'
|
|
|
|
|
logging.statusWriter(self.statusPath, message, 1)
|
|
|
|
|
elif self.path.find('vmail') > -1:
|
|
|
|
|
message = 'Restoring email..'
|
|
|
|
|
logging.statusWriter(self.statusPath, message, 1)
|
2020-01-23 23:20:06 +05:00
|
|
|
if self.restoreEmail() == 0:
|
|
|
|
|
return 0
|
2019-11-02 19:29:02 +05:00
|
|
|
message = 'Emails restored.'
|
|
|
|
|
logging.statusWriter(self.statusPath, message, 1)
|
|
|
|
|
elif self.path.find('meta.xml') > -1:
|
|
|
|
|
message = 'Reconstructing with meta..'
|
|
|
|
|
logging.statusWriter(self.statusPath, message, 1)
|
2020-01-23 23:20:06 +05:00
|
|
|
if self.reconstructWithMeta() == 0:
|
|
|
|
|
return 0
|
2019-11-02 19:29:02 +05:00
|
|
|
message = 'Reconstructed'
|
|
|
|
|
logging.statusWriter(self.statusPath, message, 1)
|
|
|
|
|
else:
|
2020-04-16 00:06:25 +05:00
|
|
|
|
2019-11-02 19:29:02 +05:00
|
|
|
self.jobid = JobSnapshots.objects.get(pk=jobid)
|
2019-10-06 18:41:09 +05:00
|
|
|
|
2020-04-16 00:06:25 +05:00
|
|
|
self.findRestorePath()
|
|
|
|
|
|
2019-11-02 19:29:02 +05:00
|
|
|
message = 'Starting restore of %s for %s.' % (self.jobid.snapshotid, self.website)
|
2019-10-15 22:59:22 +05:00
|
|
|
logging.statusWriter(self.statusPath, message, 1)
|
2019-11-02 19:29:02 +05:00
|
|
|
self.passwordFile = '/home/%s/%s' % (self.website, self.website)
|
|
|
|
|
|
|
|
|
|
##
|
|
|
|
|
|
|
|
|
|
if self.jobid.type[:8] == 'database':
|
|
|
|
|
message = 'Restoring database..'
|
|
|
|
|
logging.statusWriter(self.statusPath, message, 1)
|
|
|
|
|
self.restoreDatabase()
|
|
|
|
|
message = 'Database restored.'
|
|
|
|
|
logging.statusWriter(self.statusPath, message, 1)
|
|
|
|
|
elif self.jobid.type[:4] == 'data':
|
2020-01-23 22:51:38 +05:00
|
|
|
message = 'Restoring data..'
|
|
|
|
|
logging.statusWriter(self.statusPath, message, 1)
|
|
|
|
|
if self.restoreData() == 0:
|
|
|
|
|
return 0
|
|
|
|
|
message = 'Data restored.'
|
|
|
|
|
logging.statusWriter(self.statusPath, message, 1)
|
2019-11-02 19:29:02 +05:00
|
|
|
elif self.jobid.type[:5] == 'email':
|
|
|
|
|
message = 'Restoring email..'
|
|
|
|
|
logging.statusWriter(self.statusPath, message, 1)
|
|
|
|
|
self.restoreEmail()
|
|
|
|
|
message = 'Emails restored.'
|
|
|
|
|
logging.statusWriter(self.statusPath, message, 1)
|
|
|
|
|
elif self.jobid.type[:4] == 'meta':
|
|
|
|
|
message = 'Reconstructing with meta..'
|
|
|
|
|
logging.statusWriter(self.statusPath, message, 1)
|
|
|
|
|
self.reconstructWithMeta()
|
|
|
|
|
message = 'Reconstructed'
|
|
|
|
|
logging.statusWriter(self.statusPath, message, 1)
|
2019-10-06 18:41:09 +05:00
|
|
|
|
|
|
|
|
logging.statusWriter(self.statusPath, 'Completed', 1)
|
2019-12-10 15:09:10 +05:00
|
|
|
except BaseException as msg:
|
2019-10-06 18:41:09 +05:00
|
|
|
logging.statusWriter(self.extraArgs['tempPath'], str(msg), 1)
|
|
|
|
|
|
2019-10-15 22:59:22 +05:00
|
|
|
### Backup functions
|
|
|
|
|
|
2019-10-06 18:41:09 +05:00
|
|
|
def prepareBackupMeta(self):
|
|
|
|
|
try:
|
|
|
|
|
|
2021-05-07 22:22:29 +05:00
|
|
|
## Use the meta function from backup utils for future improvements.
|
2019-10-06 18:41:09 +05:00
|
|
|
|
2021-05-07 22:22:29 +05:00
|
|
|
if os.path.exists(ProcessUtilities.debugPath):
|
|
|
|
|
logging.writeToFile('Creating meta for %s. [IncBackupsControl.py]' % (self.website.domain))
|
2019-10-06 18:41:09 +05:00
|
|
|
|
2021-05-07 22:22:29 +05:00
|
|
|
from plogical.backupUtilities import backupUtilities
|
|
|
|
|
status, message, metaPath = backupUtilities.prepareBackupMeta(self.website.domain, None, None, None, 0)
|
2019-10-06 18:41:09 +05:00
|
|
|
|
|
|
|
|
## meta generated
|
|
|
|
|
|
2021-05-07 22:22:29 +05:00
|
|
|
if status == 1:
|
|
|
|
|
logging.statusWriter(self.statusPath, 'Meta data is ready..', 1)
|
|
|
|
|
metaPathNew = '/home/%s/meta.xml' % (self.website.domain)
|
2021-11-23 13:39:42 +05:00
|
|
|
|
|
|
|
|
command = 'chown %s:%s %s' % (self.externalApp, self.externalApp, metaPath)
|
2021-05-07 22:22:29 +05:00
|
|
|
ProcessUtilities.executioner(command)
|
2021-11-23 13:39:42 +05:00
|
|
|
|
|
|
|
|
command = 'mv %s %s' % (metaPath, metaPathNew)
|
|
|
|
|
ProcessUtilities.executioner(command, self.externalApp)
|
2021-05-07 22:22:29 +05:00
|
|
|
return 1
|
|
|
|
|
else:
|
|
|
|
|
logging.statusWriter(self.statusPath, "%s [544][5009]" % (message), 1)
|
|
|
|
|
return 0
|
2019-10-06 18:41:09 +05:00
|
|
|
|
2019-12-10 15:09:10 +05:00
|
|
|
except BaseException as msg:
|
2021-05-07 22:22:29 +05:00
|
|
|
logging.statusWriter(self.statusPath, "%s [548][5009]" % (str(msg)), 1)
|
2019-10-06 18:41:09 +05:00
|
|
|
return 0
|
|
|
|
|
|
|
|
|
|
def backupData(self):
|
|
|
|
|
try:
|
|
|
|
|
logging.statusWriter(self.statusPath, 'Backing up data..', 1)
|
2019-10-15 22:59:22 +05:00
|
|
|
backupPath = '/home/%s' % (self.website.domain)
|
2019-10-06 18:41:09 +05:00
|
|
|
|
|
|
|
|
if self.backupDestinations == 'local':
|
2020-01-23 20:53:17 +05:00
|
|
|
if self.localFunction(backupPath, 'data') == 0:
|
|
|
|
|
return 0
|
2022-04-30 00:28:28 +05:00
|
|
|
elif self.backupDestinations[:4] == 'sftp':
|
2020-01-23 20:53:17 +05:00
|
|
|
if self.sftpFunction(backupPath, 'data') == 0:
|
|
|
|
|
return 0
|
2019-10-14 17:40:58 +05:00
|
|
|
else:
|
2020-01-23 22:51:38 +05:00
|
|
|
if self.awsFunction('backup', backupPath, '', 'data') == 0:
|
|
|
|
|
return 0
|
2019-10-06 18:41:09 +05:00
|
|
|
|
2019-10-28 12:18:19 +05:00
|
|
|
logging.statusWriter(self.statusPath,
|
|
|
|
|
'Data for %s backed to %s.' % (self.website.domain, self.backupDestinations), 1)
|
2019-10-06 18:41:09 +05:00
|
|
|
return 1
|
2019-12-10 15:09:10 +05:00
|
|
|
except BaseException as msg:
|
2019-10-28 12:18:19 +05:00
|
|
|
logging.statusWriter(self.statusPath, '%s. [IncJobs.backupData.223][5009]' % str(msg), 1)
|
2019-10-06 18:41:09 +05:00
|
|
|
return 0
|
|
|
|
|
|
|
|
|
|
def backupDatabases(self):
|
|
|
|
|
try:
|
|
|
|
|
logging.statusWriter(self.statusPath, 'Backing up databases..', 1)
|
|
|
|
|
|
|
|
|
|
databases = self.website.databases_set.all()
|
|
|
|
|
|
|
|
|
|
for items in databases:
|
2021-05-07 22:22:29 +05:00
|
|
|
|
2021-11-23 19:20:11 +05:00
|
|
|
###
|
|
|
|
|
|
|
|
|
|
UploadPath = '/usr/local/CyberCP/tmp'
|
|
|
|
|
|
|
|
|
|
if not os.path.exists(UploadPath):
|
|
|
|
|
command = 'mkdir %s' % (UploadPath)
|
|
|
|
|
ProcessUtilities.executioner(command)
|
|
|
|
|
|
|
|
|
|
command = 'chown cyberpanel:cyberpanel %s' % (UploadPath)
|
|
|
|
|
ProcessUtilities.executioner(command)
|
|
|
|
|
|
|
|
|
|
command = 'chmod 711 %s' % (UploadPath)
|
|
|
|
|
ProcessUtilities.executioner(command)
|
|
|
|
|
|
|
|
|
|
###
|
|
|
|
|
|
|
|
|
|
if mysqlUtilities.mysqlUtilities.createDatabaseBackup(items.dbName, UploadPath) == 0:
|
2019-10-06 18:41:09 +05:00
|
|
|
return 0
|
|
|
|
|
|
2021-11-23 19:20:11 +05:00
|
|
|
dbPath = '%s/%s.sql' % (UploadPath, items.dbName)
|
|
|
|
|
dbPathNew = '/home/%s/%s.sql' % (self.website.domain, items.dbName)
|
|
|
|
|
|
|
|
|
|
command = 'cp %s %s' % (dbPath, dbPathNew)
|
|
|
|
|
ProcessUtilities.executioner(command, self.externalApp)
|
2019-10-06 18:41:09 +05:00
|
|
|
|
|
|
|
|
if self.backupDestinations == 'local':
|
2021-11-23 19:20:11 +05:00
|
|
|
if self.localFunction(dbPathNew, 'database') == 0:
|
2020-01-23 22:51:38 +05:00
|
|
|
return 0
|
2022-04-30 00:28:28 +05:00
|
|
|
elif self.backupDestinations[:4] == 'sftp':
|
2021-11-23 19:20:11 +05:00
|
|
|
if self.sftpFunction(dbPathNew, 'database') == 0:
|
2020-01-23 22:51:38 +05:00
|
|
|
return 0
|
2019-10-14 17:40:58 +05:00
|
|
|
else:
|
2021-11-23 19:20:11 +05:00
|
|
|
if self.awsFunction('backup', dbPathNew, '', 'database') == 0:
|
2020-01-23 22:51:38 +05:00
|
|
|
return 0
|
2019-10-06 18:41:09 +05:00
|
|
|
|
|
|
|
|
try:
|
2021-12-26 13:20:28 +05:00
|
|
|
dbPath = '/usr/local/CyberCP/tmp/%s.sql' % (items.dbName)
|
|
|
|
|
command = 'rm -f %s' % (dbPath)
|
|
|
|
|
ProcessUtilities.executioner(command, self.externalApp)
|
2019-12-10 15:09:10 +05:00
|
|
|
except BaseException as msg:
|
2019-10-28 12:18:19 +05:00
|
|
|
logging.statusWriter(self.statusPath,
|
|
|
|
|
'Failed to delete database: %s. [IncJobs.backupDatabases.456]' % str(msg), 1)
|
2021-12-26 15:30:33 +05:00
|
|
|
|
2019-10-06 18:41:09 +05:00
|
|
|
return 1
|
2019-12-10 15:09:10 +05:00
|
|
|
except BaseException as msg:
|
2019-10-28 12:18:19 +05:00
|
|
|
logging.statusWriter(self.statusPath, '%s. [IncJobs.backupDatabases.269][5009]' % str(msg), 1)
|
2019-10-06 18:41:09 +05:00
|
|
|
return 0
|
|
|
|
|
|
|
|
|
|
def emailBackup(self):
|
|
|
|
|
try:
|
|
|
|
|
logging.statusWriter(self.statusPath, 'Backing up emails..', 1)
|
|
|
|
|
|
|
|
|
|
backupPath = '/home/vmail/%s' % (self.website.domain)
|
|
|
|
|
|
2020-01-09 11:43:57 +05:00
|
|
|
if os.path.exists(backupPath):
|
2021-05-07 22:22:29 +05:00
|
|
|
|
2020-01-09 11:43:57 +05:00
|
|
|
if self.backupDestinations == 'local':
|
2020-01-23 22:51:38 +05:00
|
|
|
if self.localFunction(backupPath, 'email') == 0:
|
|
|
|
|
return 0
|
2022-04-30 00:28:28 +05:00
|
|
|
elif self.backupDestinations[:4] == 'sftp':
|
2020-01-23 22:51:38 +05:00
|
|
|
if self.sftpFunction(backupPath, 'email') == 0:
|
|
|
|
|
return 0
|
2020-01-09 11:43:57 +05:00
|
|
|
else:
|
2020-01-23 22:51:38 +05:00
|
|
|
if self.awsFunction('backup', backupPath, '', 'email') == 0:
|
|
|
|
|
return 0
|
2019-10-06 18:41:09 +05:00
|
|
|
|
2019-10-28 12:18:19 +05:00
|
|
|
logging.statusWriter(self.statusPath,
|
|
|
|
|
'Emails for %s backed to %s.' % (self.website.domain, self.backupDestinations), 1)
|
2019-10-06 18:41:09 +05:00
|
|
|
return 1
|
2019-12-10 15:09:10 +05:00
|
|
|
except BaseException as msg:
|
2019-10-28 12:18:19 +05:00
|
|
|
logging.statusWriter(self.statusPath, '%s. [IncJobs.emailBackup.269][5009]' % str(msg), 1)
|
2019-10-06 18:41:09 +05:00
|
|
|
return 0
|
|
|
|
|
|
2019-10-15 22:59:22 +05:00
|
|
|
def metaBackup(self):
|
|
|
|
|
try:
|
|
|
|
|
logging.statusWriter(self.statusPath, 'Backing up meta..', 1)
|
|
|
|
|
|
|
|
|
|
backupPath = '/home/%s/meta.xml' % (self.website.domain)
|
|
|
|
|
|
|
|
|
|
if self.backupDestinations == 'local':
|
2020-01-23 22:51:38 +05:00
|
|
|
if self.localFunction(backupPath, 'meta') == 0:
|
|
|
|
|
return 0
|
2022-04-30 00:28:28 +05:00
|
|
|
elif self.backupDestinations[:4] == 'sftp':
|
2020-01-23 22:51:38 +05:00
|
|
|
if self.sftpFunction(backupPath, 'meta') == 0:
|
|
|
|
|
return 0
|
2019-10-15 22:59:22 +05:00
|
|
|
else:
|
2020-01-23 22:51:38 +05:00
|
|
|
if self.awsFunction('backup', backupPath, '', 'meta') == 0:
|
|
|
|
|
return 0
|
2019-10-15 22:59:22 +05:00
|
|
|
|
2019-10-28 12:18:19 +05:00
|
|
|
logging.statusWriter(self.statusPath,
|
|
|
|
|
'Meta for %s backed to %s.' % (self.website.domain, self.backupDestinations), 1)
|
2019-10-15 22:59:22 +05:00
|
|
|
return 1
|
2019-12-10 15:09:10 +05:00
|
|
|
except BaseException as msg:
|
2019-10-28 12:18:19 +05:00
|
|
|
logging.statusWriter(self.statusPath, '%s. [IncJobs.metaBackup.269][5009]' % str(msg), 1)
|
2019-10-15 22:59:22 +05:00
|
|
|
return 0
|
|
|
|
|
|
2019-10-06 18:41:09 +05:00
|
|
|
def initiateRepo(self):
|
2022-04-30 00:28:28 +05:00
|
|
|
try:
|
|
|
|
|
logging.statusWriter(self.statusPath, 'Will first initiate backup repo..', 1)
|
|
|
|
|
|
2019-10-06 18:41:09 +05:00
|
|
|
if self.backupDestinations == 'local':
|
2022-04-30 00:28:28 +05:00
|
|
|
command = 'restic init --repo %s --password-file %s' % (self.repoPath, self.passwordFile)
|
|
|
|
|
result = ProcessUtilities.outputExecutioner(command, self.externalApp)
|
|
|
|
|
|
|
|
|
|
if os.path.exists(ProcessUtilities.debugPath):
|
|
|
|
|
logging.writeToFile(result)
|
|
|
|
|
|
|
|
|
|
if result.find('config file already exists') == -1:
|
|
|
|
|
logging.statusWriter(self.statusPath, result, 1)
|
|
|
|
|
|
|
|
|
|
elif self.backupDestinations[:4] == 'sftp':
|
|
|
|
|
remotePath = '/home/backup/%s' % (self.website.domain)
|
|
|
|
|
command = 'export PATH=${PATH}:/usr/bin && restic init --repo %s:%s --password-file %s' % (
|
|
|
|
|
self.backupDestinations, remotePath, self.passwordFile)
|
|
|
|
|
result = ProcessUtilities.outputExecutioner(command, self.externalApp)
|
|
|
|
|
|
|
|
|
|
if os.path.exists(ProcessUtilities.debugPath):
|
|
|
|
|
logging.writeToFile(result)
|
|
|
|
|
|
|
|
|
|
if result.find('config file already exists') == -1:
|
|
|
|
|
logging.statusWriter(self.statusPath, result, 1)
|
2019-10-06 18:41:09 +05:00
|
|
|
else:
|
2022-04-30 00:28:28 +05:00
|
|
|
key, secret = self.getAWSData()
|
|
|
|
|
command = 'export AWS_ACCESS_KEY_ID=%s AWS_SECRET_ACCESS_KEY=%s && restic -r s3:s3.amazonaws.com/%s init --password-file %s' % (
|
|
|
|
|
key, secret, self.website.domain, self.passwordFile)
|
|
|
|
|
result = ProcessUtilities.outputExecutioner(command, self.externalApp)
|
|
|
|
|
|
2021-05-07 02:10:51 +05:00
|
|
|
if os.path.exists(ProcessUtilities.debugPath):
|
|
|
|
|
logging.writeToFile(result)
|
2022-04-30 00:28:28 +05:00
|
|
|
|
|
|
|
|
if result.find('config file already exists') == -1:
|
|
|
|
|
logging.statusWriter(self.statusPath, result, 1)
|
|
|
|
|
|
|
|
|
|
logging.statusWriter(self.statusPath,
|
|
|
|
|
'Repo %s initiated for %s.' % (self.backupDestinations, self.website.domain), 1)
|
2019-10-06 18:41:09 +05:00
|
|
|
return 1
|
2019-12-10 15:09:10 +05:00
|
|
|
except BaseException as msg:
|
2019-10-28 12:18:19 +05:00
|
|
|
logging.statusWriter(self.statusPath, '%s. [IncJobs.initiateRepo.47][5009]' % str(msg), 1)
|
2019-10-06 18:41:09 +05:00
|
|
|
return 0
|
|
|
|
|
|
2020-01-23 20:53:17 +05:00
|
|
|
def sendEmail(self, password):
|
|
|
|
|
SUBJECT = "Backup Repository password for %s" % (self.website.domain)
|
|
|
|
|
text = """Password: %s
|
|
|
|
|
This is password for your incremental backup repository, please save it in safe place as it will be required when you want to restore backup for this site on remote server.
|
|
|
|
|
""" % (password)
|
|
|
|
|
|
|
|
|
|
sender = 'cyberpanel@%s' % (self.website.domain)
|
|
|
|
|
TO = [self.website.adminEmail]
|
|
|
|
|
message = """\
|
|
|
|
|
From: %s
|
|
|
|
|
To: %s
|
|
|
|
|
Subject: %s
|
|
|
|
|
|
|
|
|
|
%s
|
|
|
|
|
""" % (sender, ", ".join(TO), SUBJECT, text)
|
|
|
|
|
mailUtilities.SendEmail(sender, TO, message)
|
|
|
|
|
|
2019-10-06 18:41:09 +05:00
|
|
|
def createBackup(self):
|
2021-05-07 02:10:51 +05:00
|
|
|
|
2021-12-25 14:03:11 +05:00
|
|
|
try:
|
2019-10-06 18:41:09 +05:00
|
|
|
|
2021-12-25 14:03:11 +05:00
|
|
|
self.statusPath = self.extraArgs['tempPath']
|
|
|
|
|
website = self.extraArgs['website']
|
|
|
|
|
self.backupDestinations = self.extraArgs['backupDestinations']
|
|
|
|
|
websiteData = self.extraArgs['websiteData']
|
|
|
|
|
websiteEmails = self.extraArgs['websiteEmails']
|
|
|
|
|
websiteDatabases = self.extraArgs['websiteDatabases']
|
2020-01-23 20:53:17 +05:00
|
|
|
|
2021-12-25 14:03:11 +05:00
|
|
|
### Checking if restic is installed before moving on
|
2021-05-07 02:10:51 +05:00
|
|
|
|
2022-04-30 00:28:28 +05:00
|
|
|
command = 'restic'
|
2021-04-19 13:09:41 -04:00
|
|
|
|
2022-04-30 00:28:28 +05:00
|
|
|
if ProcessUtilities.outputExecutioner(command).find('restic is a backup program which') == -1:
|
2021-12-25 14:03:11 +05:00
|
|
|
try:
|
2021-04-17 23:16:48 -04:00
|
|
|
|
2021-12-25 14:03:11 +05:00
|
|
|
CentOSPath = '/etc/redhat-release'
|
|
|
|
|
|
|
|
|
|
if os.path.exists(CentOSPath):
|
|
|
|
|
command = 'yum install -y yum-plugin-copr'
|
|
|
|
|
ProcessUtilities.executioner(command)
|
|
|
|
|
command = 'yum copr enable -y copart/restic'
|
|
|
|
|
ProcessUtilities.executioner(command)
|
|
|
|
|
command = 'yum install -y restic'
|
|
|
|
|
ProcessUtilities.executioner(command)
|
|
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
command = 'apt-get update -y'
|
2021-04-18 21:44:54 -04:00
|
|
|
ProcessUtilities.executioner(command)
|
2021-12-25 14:03:11 +05:00
|
|
|
|
|
|
|
|
command = 'apt-get install restic -y'
|
2021-04-17 23:16:48 -04:00
|
|
|
ProcessUtilities.executioner(command)
|
2021-04-19 13:09:41 -04:00
|
|
|
|
2021-12-25 14:03:11 +05:00
|
|
|
except:
|
|
|
|
|
logging.statusWriter(self.statusPath,
|
|
|
|
|
'It seems restic is not installed, for incremental backups to work '
|
|
|
|
|
'restic must be installed. You can manually install restic using this '
|
|
|
|
|
'guide -> https://go.cyberpanel.net/restic. [5009]', 1)
|
|
|
|
|
pass
|
2021-04-17 23:16:48 -04:00
|
|
|
|
2021-12-25 14:03:11 +05:00
|
|
|
return 0
|
2021-04-17 23:16:48 -04:00
|
|
|
|
2021-12-25 14:03:11 +05:00
|
|
|
## Restic check completed.
|
2021-04-17 23:16:48 -04:00
|
|
|
|
2021-12-25 14:03:11 +05:00
|
|
|
self.website = Websites.objects.get(domain=website)
|
|
|
|
|
self.externalApp = self.website.externalApp
|
2020-01-23 20:53:17 +05:00
|
|
|
|
2021-12-25 14:03:11 +05:00
|
|
|
self.jobid = IncJob(website=self.website)
|
|
|
|
|
self.jobid.save()
|
2019-10-06 18:41:09 +05:00
|
|
|
|
2021-12-25 14:03:11 +05:00
|
|
|
self.passwordFile = '/home/%s/%s' % (self.website.domain, self.website.domain)
|
2019-10-06 18:41:09 +05:00
|
|
|
|
2021-12-25 14:03:11 +05:00
|
|
|
self.repoPath = '/home/%s/incbackup' % (self.website.domain)
|
2019-10-06 18:41:09 +05:00
|
|
|
|
2021-12-25 14:03:11 +05:00
|
|
|
command = 'ls -la %s' % (self.passwordFile)
|
|
|
|
|
output = ProcessUtilities.outputExecutioner(command, self.externalApp)
|
2019-10-06 18:41:09 +05:00
|
|
|
|
2021-12-25 14:03:11 +05:00
|
|
|
if output.find('No such file or directory') > -1:
|
|
|
|
|
password = randomPassword.generate_pass()
|
|
|
|
|
command = 'echo "%s" > %s' % (password, self.passwordFile)
|
|
|
|
|
ProcessUtilities.executioner(command, self.externalApp, True)
|
2019-10-06 18:41:09 +05:00
|
|
|
|
2021-12-25 14:03:11 +05:00
|
|
|
command = 'chmod 600 %s' % (self.passwordFile)
|
|
|
|
|
ProcessUtilities.executioner(command, self.externalApp)
|
2021-11-23 13:39:42 +05:00
|
|
|
|
2021-12-25 14:03:11 +05:00
|
|
|
self.sendEmail(password)
|
2019-10-06 18:41:09 +05:00
|
|
|
|
2021-12-25 14:03:11 +05:00
|
|
|
## Completed password generation
|
2019-11-02 19:29:02 +05:00
|
|
|
|
2021-12-25 14:03:11 +05:00
|
|
|
if self.initiateRepo() == 0:
|
2022-04-30 00:28:28 +05:00
|
|
|
return 0
|
2019-10-15 22:59:22 +05:00
|
|
|
|
2021-12-25 14:03:11 +05:00
|
|
|
if self.prepareBackupMeta() == 0:
|
|
|
|
|
return 0
|
2020-01-23 22:51:38 +05:00
|
|
|
|
2021-12-25 14:03:11 +05:00
|
|
|
if websiteData:
|
|
|
|
|
if self.backupData() == 0:
|
|
|
|
|
return 0
|
2019-10-06 18:41:09 +05:00
|
|
|
|
2021-12-25 14:03:11 +05:00
|
|
|
if websiteDatabases:
|
|
|
|
|
if self.backupDatabases() == 0:
|
|
|
|
|
return 0
|
2019-10-06 18:41:09 +05:00
|
|
|
|
2021-12-25 14:03:11 +05:00
|
|
|
if websiteEmails:
|
|
|
|
|
if self.emailBackup() == 0:
|
|
|
|
|
return 0
|
2019-10-06 18:41:09 +05:00
|
|
|
|
2021-12-25 14:03:11 +05:00
|
|
|
## Backup job done
|
2019-10-06 18:41:09 +05:00
|
|
|
|
2021-12-25 14:03:11 +05:00
|
|
|
self.metaBackup()
|
2019-10-06 18:41:09 +05:00
|
|
|
|
2021-12-25 14:03:11 +05:00
|
|
|
metaPathNew = '/home/%s/meta.xml' % (self.website.domain)
|
2020-01-23 22:51:38 +05:00
|
|
|
|
2021-12-25 14:03:11 +05:00
|
|
|
try:
|
|
|
|
|
command = 'rm -f %s' % (metaPathNew)
|
|
|
|
|
ProcessUtilities.executioner(command)
|
|
|
|
|
except BaseException as msg:
|
|
|
|
|
logging.statusWriter(self.statusPath,
|
|
|
|
|
'Failed to delete meta file: %s. [IncJobs.createBackup.591]' % str(msg), 1)
|
2019-10-06 18:41:09 +05:00
|
|
|
|
2021-12-25 14:03:11 +05:00
|
|
|
logging.statusWriter(self.statusPath, 'Completed', 1)
|
2019-10-06 18:41:09 +05:00
|
|
|
|
2019-12-10 15:09:10 +05:00
|
|
|
except BaseException as msg:
|
2019-10-28 12:18:19 +05:00
|
|
|
logging.statusWriter(self.statusPath,
|
2021-12-25 14:03:11 +05:00
|
|
|
'Failed to create incremental backup: %s. [5009][IncJobs.createBackup.913]' % str(msg), 1)
|
2019-10-06 18:41:09 +05:00
|
|
|
|
2021-05-07 22:22:29 +05:00
|
|
|
|
|
|
|
|
### Delete Snapshot
|
|
|
|
|
|
|
|
|
|
def DeleteSnapShot(self, inc_job):
|
|
|
|
|
try:
|
|
|
|
|
|
|
|
|
|
self.statusPath = logging.fileName
|
|
|
|
|
|
|
|
|
|
job_snapshots = inc_job.jobsnapshots_set.all()
|
|
|
|
|
|
|
|
|
|
### Fetch the website name from JobSnapshot object and set these variable as they are needed in called functions below
|
|
|
|
|
|
|
|
|
|
self.website = job_snapshots[0].job.website.domain
|
2021-11-23 13:39:42 +05:00
|
|
|
self.externalApp = job_snapshots[0].job.website.externalApp
|
2021-05-07 22:22:29 +05:00
|
|
|
self.passwordFile = '/home/%s/%s' % (self.website, self.website)
|
2022-04-30 00:28:28 +05:00
|
|
|
|
2021-05-07 22:22:29 +05:00
|
|
|
for job_snapshot in job_snapshots:
|
|
|
|
|
|
2022-04-30 00:28:28 +05:00
|
|
|
## Functions above use the self.jobid varilable to extract information about this snapshot, so this below variable needs to be set
|
|
|
|
|
|
2021-05-07 22:22:29 +05:00
|
|
|
self.jobid = job_snapshot
|
|
|
|
|
|
2022-04-30 00:28:28 +05:00
|
|
|
if self.jobid.destination == 'local':
|
|
|
|
|
self.localFunction('none', 'none', 0, 1)
|
|
|
|
|
elif self.jobid.destination[:4] == 'sftp':
|
|
|
|
|
self.sftpFunction('none', 'none', 0, 1)
|
|
|
|
|
else:
|
|
|
|
|
self.awsFunction('restore', '', self.jobid.snapshotid, None, 1)
|
2021-05-07 22:22:29 +05:00
|
|
|
|
|
|
|
|
return 1
|
|
|
|
|
|
|
|
|
|
except BaseException as msg:
|
|
|
|
|
logging.statusWriter(self.statusPath, "%s [903:DeleteSnapShot][5009]" % (str(msg)), 1)
|
2022-04-30 00:28:28 +05:00
|
|
|
return 0
|