mirror of
https://github.com/usmannasir/cyberpanel.git
synced 2025-11-08 06:16:08 +01:00
incremental backups: completion and s3:aws integration
This commit is contained in:
31
.idea/CyberCP.iml
generated
Executable file
31
.idea/CyberCP.iml
generated
Executable file
@@ -0,0 +1,31 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="PYTHON_MODULE" version="4">
|
||||
<component name="FacetManager">
|
||||
<facet type="django" name="Django">
|
||||
<configuration>
|
||||
<option name="rootFolder" value="$MODULE_DIR$" />
|
||||
<option name="settingsModule" value="CyberCP/settings.py" />
|
||||
<option name="manageScript" value="$MODULE_DIR$/manage.py" />
|
||||
<option name="environment" value="<map/>" />
|
||||
<option name="doNotUseTestRunner" value="false" />
|
||||
<option name="trackFilePattern" value="migrations" />
|
||||
</configuration>
|
||||
</facet>
|
||||
</component>
|
||||
<component name="NewModuleRootManager">
|
||||
<content url="file://$MODULE_DIR$" />
|
||||
<orderEntry type="jdk" jdkName="Python 2.7" jdkType="Python SDK" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
<component name="TemplatesService">
|
||||
<option name="TEMPLATE_CONFIGURATION" value="Django" />
|
||||
<option name="TEMPLATE_FOLDERS">
|
||||
<list>
|
||||
<option value="$MODULE_DIR$/dns/templates" />
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
<component name="TestRunnerService">
|
||||
<option name="PROJECT_TEST_RUNNER" value="Unittests" />
|
||||
</component>
|
||||
</module>
|
||||
7
.idea/misc.xml
generated
Executable file
7
.idea/misc.xml
generated
Executable file
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="JavaScriptSettings">
|
||||
<option name="languageLevel" value="ES6" />
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" project-jdk-name="Python 2.7" project-jdk-type="Python SDK" />
|
||||
</project>
|
||||
8
.idea/modules.xml
generated
Executable file
8
.idea/modules.xml
generated
Executable file
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/CyberCP.iml" filepath="$PROJECT_DIR$/.idea/CyberCP.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
1172
.idea/workspace.xml
generated
Executable file
1172
.idea/workspace.xml
generated
Executable file
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,7 @@
|
||||
from plogical.CyberCPLogFileWriter import CyberCPLogFileWriter as logging
|
||||
import json
|
||||
from django.shortcuts import HttpResponse
|
||||
import re
|
||||
|
||||
class secMiddleware:
|
||||
|
||||
@@ -58,6 +59,14 @@ class secMiddleware:
|
||||
else:
|
||||
continue
|
||||
|
||||
if key == 'backupDestinations':
|
||||
if re.match('^[a-z|0-9]+:[a-z|0-9|\.]+\/?[A-Z|a-z|0-9|\.]*$', value) == None and value != 'local':
|
||||
logging.writeToFile(request.body)
|
||||
final_dic = {'error_message': "Data supplied is not accepted.",
|
||||
"errorMessage": "Data supplied is not accepted."}
|
||||
final_json = json.dumps(final_dic)
|
||||
return HttpResponse(final_json)
|
||||
|
||||
if request.build_absolute_uri().find('saveSpamAssassinConfigurations') > -1 or request.build_absolute_uri().find('docker') > -1 or request.build_absolute_uri().find('cloudAPI') > -1 or request.build_absolute_uri().find('filemanager') > -1 or request.build_absolute_uri().find('verifyLogin') > -1 or request.build_absolute_uri().find('submitUserCreation') > -1:
|
||||
continue
|
||||
if key == 'backupDestinations' or key == 'ports' or key == 'imageByPass' or key == 'passwordByPass' or key == 'cronCommand' or key == 'emailMessage' or key == 'configData' or key == 'rewriteRules' or key == 'modSecRules' or key == 'recordContentTXT' or key == 'SecAuditLogRelevantStatus' or key == 'fileContent':
|
||||
|
||||
@@ -52,6 +52,42 @@ class IncJobs(multi.Thread):
|
||||
elif self.function == 'restorePoint':
|
||||
self.restorePoint()
|
||||
|
||||
def getAWSData(self):
|
||||
key = self.backupDestinations.split('/')[-1]
|
||||
path = '/home/cyberpanel/aws/%s' % (key)
|
||||
secret = open(path, 'r').read()
|
||||
return key, secret
|
||||
|
||||
def awsFunction(self, fType, backupPath = None, snapshotID = None, bType = None):
|
||||
try:
|
||||
if fType == 'backup':
|
||||
key, secret = self.getAWSData()
|
||||
command = 'export AWS_ACCESS_KEY_ID=%s AWS_SECRET_ACCESS_KEY=%s && restic -r s3:s3.amazonaws.com/%s backup %s --password-file %s' % (
|
||||
key, secret, self.website.domain, backupPath, self.passwordFile)
|
||||
result = ProcessUtilities.outputExecutioner(command)
|
||||
logging.statusWriter(self.statusPath, result, 1)
|
||||
snapShotid = result.split(' ')[-2]
|
||||
if bType == 'database':
|
||||
newSnapshot = JobSnapshots(job=self.jobid, type='%s:%s' % (bType, backupPath.split('/')[-1].strip('.sql')),
|
||||
snapshotid=snapShotid,
|
||||
destination=self.backupDestinations)
|
||||
else:
|
||||
newSnapshot = JobSnapshots(job=self.jobid, type='%s:%s' % (bType, backupPath), snapshotid=snapShotid,
|
||||
destination=self.backupDestinations)
|
||||
newSnapshot.save()
|
||||
else:
|
||||
self.backupDestinations = self.jobid.destination
|
||||
key, secret = self.getAWSData()
|
||||
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 /' % (
|
||||
key, secret, self.website, snapshotID, self.passwordFile)
|
||||
result = ProcessUtilities.outputExecutioner(command)
|
||||
logging.statusWriter(self.statusPath, result, 1)
|
||||
|
||||
|
||||
except BaseException, msg:
|
||||
logging.statusWriter(self.statusPath, "%s [46][5009]" % (str(msg)), 1)
|
||||
return 0
|
||||
|
||||
def restoreData(self):
|
||||
try:
|
||||
|
||||
@@ -65,6 +101,8 @@ class IncJobs(multi.Thread):
|
||||
command = 'export PATH=${PATH}:/usr/bin && restic -r %s:%s restore %s --target / --password-file %s' % (self.jobid.destination, repoLocation, self.jobid.snapshotid, self.passwordFile)
|
||||
result = ProcessUtilities.outputExecutioner(command)
|
||||
logging.statusWriter(self.statusPath, result, 1)
|
||||
else:
|
||||
self.awsFunction('restore', '', self.jobid.snapshotid)
|
||||
|
||||
except BaseException, msg:
|
||||
logging.statusWriter(self.statusPath, "%s [46][5009]" % (str(msg)), 1)
|
||||
@@ -83,8 +121,10 @@ class IncJobs(multi.Thread):
|
||||
command = 'export PATH=${PATH}:/usr/bin && restic -r %s:%s restore %s --target / --password-file %s' % (self.jobid.destination, repoLocation, self.jobid.snapshotid, self.passwordFile)
|
||||
result = ProcessUtilities.outputExecutioner(command)
|
||||
logging.statusWriter(self.statusPath, result, 1)
|
||||
else:
|
||||
self.awsFunction('restore', '', self.jobid.snapshotid)
|
||||
|
||||
if mysqlUtilities.mysqlUtilities.restoreDatabaseBackup(self.jobid.type.split(':')[1], '/home/cyberpanel', 'dummy', 'dummy') == 0:
|
||||
if mysqlUtilities.mysqlUtilities.restoreDatabaseBackup(self.jobid.type.split(':')[1].rstrip('.sql'), '/home/cyberpanel', 'dummy', 'dummy') == 0:
|
||||
raise BaseException
|
||||
|
||||
try:
|
||||
@@ -109,6 +149,8 @@ class IncJobs(multi.Thread):
|
||||
command = 'export PATH=${PATH}:/usr/bin && restic -r %s:%s restore %s --target / --password-file %s' % (self.jobid.destination, repoLocation, self.jobid.snapshotid, self.passwordFile)
|
||||
result = ProcessUtilities.outputExecutioner(command)
|
||||
logging.statusWriter(self.statusPath, result, 1)
|
||||
else:
|
||||
self.awsFunction('restore', '', self.jobid.snapshotid)
|
||||
|
||||
except BaseException, msg:
|
||||
logging.statusWriter(self.statusPath, "%s [46][5009]" % (str(msg)), 1)
|
||||
@@ -364,6 +406,9 @@ class IncJobs(multi.Thread):
|
||||
newSnapshot = JobSnapshots(job=self.jobid, type='data:%s' % (remotePath), snapshotid=snapShotid,
|
||||
destination=self.backupDestinations)
|
||||
newSnapshot.save()
|
||||
else:
|
||||
backupPath = '/home/%s' % (self.website.domain)
|
||||
self.awsFunction('backup', backupPath, '', 'data')
|
||||
|
||||
logging.statusWriter(self.statusPath, 'Data for %s backed to %s.' % (self.website.domain, self.backupDestinations), 1)
|
||||
return 1
|
||||
@@ -402,6 +447,8 @@ class IncJobs(multi.Thread):
|
||||
newSnapshot = JobSnapshots(job=self.jobid, type='database:%s' % (items.dbName), snapshotid=snapShotid,
|
||||
destination=self.backupDestinations)
|
||||
newSnapshot.save()
|
||||
else:
|
||||
self.awsFunction('backup', dbPath, '', 'database')
|
||||
|
||||
try:
|
||||
os.remove('/home/cyberpanel/%s' % (items.dbName))
|
||||
@@ -439,6 +486,8 @@ class IncJobs(multi.Thread):
|
||||
newSnapshot = JobSnapshots(job=self.jobid, type='email:%s' % (backupPath), snapshotid=snapShotid,
|
||||
destination=self.backupDestinations)
|
||||
newSnapshot.save()
|
||||
else:
|
||||
self.awsFunction('backup', backupPath, '', 'email')
|
||||
|
||||
|
||||
logging.statusWriter(self.statusPath, 'Emails for %s backed to %s.' % (self.website.domain, self.backupDestinations), 1)
|
||||
@@ -462,8 +511,11 @@ class IncJobs(multi.Thread):
|
||||
result = ProcessUtilities.outputExecutioner(command)
|
||||
logging.statusWriter(self.statusPath, result, 1)
|
||||
else:
|
||||
logging.statusWriter(self.statusPath, 'AWS implementation is currently pending. [5009]', 1)
|
||||
return 0
|
||||
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)
|
||||
logging.statusWriter(self.statusPath, result, 1)
|
||||
return 1
|
||||
|
||||
logging.statusWriter(self.statusPath, 'Repo %s initiated for %s.' % (self.backupDestinations, self.website.domain), 1)
|
||||
return 1
|
||||
|
||||
99
IncBackups/IncScheduler.py
Normal file
99
IncBackups/IncScheduler.py
Normal file
@@ -0,0 +1,99 @@
|
||||
#!/usr/local/CyberCP/bin/python2
|
||||
import os
|
||||
import os.path
|
||||
import sys
|
||||
sys.path.append('/usr/local/CyberCP')
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "CyberCP.settings")
|
||||
|
||||
import django
|
||||
try:
|
||||
django.setup()
|
||||
except:
|
||||
pass
|
||||
from IncBackupsControl import IncJobs
|
||||
from IncBackups.models import BackupJob
|
||||
from random import randint
|
||||
import argparse
|
||||
try:
|
||||
from plogical.virtualHostUtilities import virtualHostUtilities
|
||||
from plogical.mailUtilities import mailUtilities
|
||||
from plogical.CyberCPLogFileWriter import CyberCPLogFileWriter as logging
|
||||
except:
|
||||
pass
|
||||
|
||||
class IncScheduler():
|
||||
logPath = '/home/cyberpanel/incbackuplogs'
|
||||
|
||||
@staticmethod
|
||||
def startBackup(type):
|
||||
try:
|
||||
logging.statusWriter(IncScheduler.logPath, 'Starting Incremental Backup job..', 1)
|
||||
tempPath = "/home/cyberpanel/" + str(randint(1000, 9999))
|
||||
for job in BackupJob.objects.all():
|
||||
logging.statusWriter(IncScheduler.logPath, 'Job Description:\n\n Destination: %s, Frequency: %s.\n ' % (job.destination, job.frequency), 1)
|
||||
if job.frequency == type:
|
||||
for web in job.jobsites_set.all():
|
||||
logging.statusWriter(IncScheduler.logPath, 'Backing up %s.' % (web.website), 1)
|
||||
extraArgs = {}
|
||||
extraArgs['website'] = web.website
|
||||
extraArgs['tempPath'] = tempPath
|
||||
extraArgs['backupDestinations'] = job.destination
|
||||
|
||||
if job.websiteData == 1:
|
||||
extraArgs['websiteData'] = True
|
||||
else:
|
||||
extraArgs['websiteData'] = False
|
||||
|
||||
if job.websiteDatabases == 1:
|
||||
extraArgs['websiteDatabases'] = True
|
||||
else:
|
||||
extraArgs['websiteDatabases'] = False
|
||||
|
||||
if job.websiteDataEmails == 1:
|
||||
extraArgs['websiteEmails'] = True
|
||||
else:
|
||||
extraArgs['websiteEmails'] = False
|
||||
|
||||
extraArgs['websiteSSLs'] = False
|
||||
|
||||
startJob = IncJobs('createBackup', extraArgs)
|
||||
startJob.start()
|
||||
|
||||
### Checking status
|
||||
|
||||
while True:
|
||||
if os.path.exists(tempPath):
|
||||
result = open(tempPath, 'r').read()
|
||||
|
||||
if result.find("Completed") > -1:
|
||||
|
||||
### Removing Files
|
||||
|
||||
os.remove(tempPath)
|
||||
|
||||
logging.statusWriter(IncScheduler.logPath, 'Backed up %s.' % (web.website), 1)
|
||||
break
|
||||
elif result.find("[5009]") > -1:
|
||||
## removing status file, so that backup can re-runn
|
||||
try:
|
||||
os.remove(tempPath)
|
||||
except:
|
||||
pass
|
||||
|
||||
logging.statusWriter(IncScheduler.logPath, 'Failed backup for %s, error: %s.' % (web.website, result), 1)
|
||||
break
|
||||
except BaseException, msg:
|
||||
logging.writeToFile(str(msg))
|
||||
|
||||
|
||||
def main():
|
||||
|
||||
parser = argparse.ArgumentParser(description='CyberPanel Installer')
|
||||
parser.add_argument('function', help='Specific a function to call!')
|
||||
args = parser.parse_args()
|
||||
|
||||
IncScheduler.startBackup(args.function)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -13,3 +13,18 @@ class JobSnapshots(models.Model):
|
||||
type = models.CharField(max_length=300)
|
||||
snapshotid = models.CharField(max_length=50)
|
||||
destination = models.CharField(max_length=200, default='')
|
||||
|
||||
|
||||
class BackupJob(models.Model):
|
||||
destination = models.CharField(max_length=300)
|
||||
frequency = models.CharField(max_length=50)
|
||||
websiteData = models.IntegerField()
|
||||
websiteDatabases = models.IntegerField()
|
||||
websiteDataEmails = models.IntegerField()
|
||||
|
||||
|
||||
class JobSites(models.Model):
|
||||
job = models.ForeignKey(BackupJob)
|
||||
website = models.CharField(max_length=300)
|
||||
|
||||
|
||||
|
||||
@@ -156,7 +156,8 @@ app.controller('createIncrementalBackups', function ($scope, $http, $timeout) {
|
||||
if (response.data.status === 1) {
|
||||
$scope.tempPath = response.data.tempPath;
|
||||
getBackupStatus();
|
||||
}else{
|
||||
} else {
|
||||
$scope.cyberpanelLoading = true;
|
||||
new PNotify({
|
||||
title: 'Operation Failed!',
|
||||
text: response.data.error_message,
|
||||
@@ -198,7 +199,7 @@ app.controller('createIncrementalBackups', function ($scope, $http, $timeout) {
|
||||
|
||||
$scope.populateCurrentRecords();
|
||||
|
||||
}else{
|
||||
} else {
|
||||
new PNotify({
|
||||
title: 'Operation Failed!',
|
||||
text: response.data.error_message,
|
||||
@@ -273,7 +274,7 @@ app.controller('createIncrementalBackups', function ($scope, $http, $timeout) {
|
||||
|
||||
var data = {
|
||||
websiteToBeBacked: $scope.websiteToBeBacked,
|
||||
jobid : id,
|
||||
jobid: id,
|
||||
reconstruct: reconstruct
|
||||
|
||||
};
|
||||
@@ -317,6 +318,7 @@ app.controller('incrementalDestinations', function ($scope, $http) {
|
||||
|
||||
if ($scope.destinationType === 'SFTP') {
|
||||
$scope.sftpHide = false;
|
||||
$scope.awsHide = true;
|
||||
$scope.populateCurrentRecords();
|
||||
} else {
|
||||
$scope.sftpHide = true;
|
||||
@@ -492,3 +494,252 @@ app.controller('incrementalDestinations', function ($scope, $http) {
|
||||
|
||||
|
||||
});
|
||||
|
||||
|
||||
app.controller('scheduleBackupInc', function ($scope, $http) {
|
||||
|
||||
var globalPageNumber;
|
||||
$scope.scheduleFreq = true;
|
||||
$scope.cyberpanelLoading = true;
|
||||
$scope.getFurtherWebsitesFromDB = function (pageNumber) {
|
||||
$scope.cyberpanelLoading = false;
|
||||
globalPageNumber = pageNumber;
|
||||
|
||||
var config = {
|
||||
headers: {
|
||||
'X-CSRFToken': getCookie('csrftoken')
|
||||
}
|
||||
};
|
||||
|
||||
var data = {page: pageNumber};
|
||||
|
||||
|
||||
dataurl = "/CloudLinux/submitWebsiteListing";
|
||||
|
||||
$http.post(dataurl, data, config).then(ListInitialData, cantLoadInitialData);
|
||||
|
||||
|
||||
function ListInitialData(response) {
|
||||
$scope.cyberpanelLoading = true;
|
||||
if (response.data.listWebSiteStatus === 1) {
|
||||
var finalData = JSON.parse(response.data.data);
|
||||
$scope.WebSitesList = finalData;
|
||||
$scope.pagination = response.data.pagination;
|
||||
$scope.default = response.data.default;
|
||||
$("#listFail").hide();
|
||||
} else {
|
||||
$("#listFail").fadeIn();
|
||||
$scope.errorMessage = response.data.error_message;
|
||||
console.log(response.data);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
function cantLoadInitialData(response) {
|
||||
$scope.cyberpanelLoading = true;
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
var websitesToBeBacked = [];
|
||||
var websitesToBeBackedTemp = [];
|
||||
|
||||
var index = 0;
|
||||
var tempTransferDir = "";
|
||||
$scope.addRemoveWebsite = function (website, websiteStatus) {
|
||||
|
||||
if (websiteStatus === true) {
|
||||
var check = 1;
|
||||
for (var j = 0; j < websitesToBeBacked.length; j++) {
|
||||
if (websitesToBeBacked[j] == website) {
|
||||
check = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (check == 1) {
|
||||
websitesToBeBacked.push(website);
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
var tempArray = [];
|
||||
|
||||
for (var j = 0; j < websitesToBeBacked.length; j++) {
|
||||
if (websitesToBeBacked[j] != website) {
|
||||
tempArray.push(websitesToBeBacked[j]);
|
||||
}
|
||||
}
|
||||
websitesToBeBacked = tempArray;
|
||||
}
|
||||
};
|
||||
|
||||
$scope.allChecked = function (webSiteStatus) {
|
||||
if (webSiteStatus === true) {
|
||||
|
||||
websitesToBeBacked = websitesToBeBackedTemp;
|
||||
$scope.webSiteStatus = true;
|
||||
} else {
|
||||
websitesToBeBacked = [];
|
||||
$scope.webSiteStatus = false;
|
||||
}
|
||||
};
|
||||
|
||||
$scope.scheduleFreqView = function () {
|
||||
$scope.scheduleFreq = false;
|
||||
$scope.getFurtherWebsitesFromDB(1);
|
||||
|
||||
};
|
||||
$scope.addSchedule = function () {
|
||||
$scope.cyberpanelLoading = false;
|
||||
|
||||
|
||||
url = "/IncrementalBackups/submitBackupSchedule";
|
||||
|
||||
var data = {
|
||||
backupDestinations: $scope.backupDest,
|
||||
backupFreq: $scope.backupFreq,
|
||||
websiteData: $scope.websiteData,
|
||||
websiteEmails: $scope.websiteEmails,
|
||||
websiteDatabases: $scope.websiteDatabases,
|
||||
websitesToBeBacked: websitesToBeBacked
|
||||
};
|
||||
|
||||
var config = {
|
||||
headers: {
|
||||
'X-CSRFToken': getCookie('csrftoken')
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
$http.post(url, data, config).then(ListInitialDatas, cantLoadInitialDatas);
|
||||
|
||||
|
||||
function ListInitialDatas(response) {
|
||||
$scope.cyberpanelLoading = true;
|
||||
$scope.populateCurrentRecords();
|
||||
if (response.data.status === 1) {
|
||||
new PNotify({
|
||||
title: 'Success!',
|
||||
text: 'Destination successfully removed.',
|
||||
type: 'success'
|
||||
});
|
||||
} else {
|
||||
new PNotify({
|
||||
title: 'Operation Failed!',
|
||||
text: response.data.error_message,
|
||||
type: 'error'
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function cantLoadInitialDatas(response) {
|
||||
$scope.cyberpanelLoading = true;
|
||||
new PNotify({
|
||||
title: 'Operation Failed!',
|
||||
text: 'Could not connect to server, please refresh this page',
|
||||
type: 'error'
|
||||
});
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
$scope.populateCurrentRecords = function () {
|
||||
|
||||
$scope.cyberpanelLoading = false;
|
||||
|
||||
|
||||
url = "/IncrementalBackups/getCurrentBackupSchedules";
|
||||
|
||||
|
||||
var data = {};
|
||||
|
||||
var config = {
|
||||
headers: {
|
||||
'X-CSRFToken': getCookie('csrftoken')
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
$http.post(url, data, config).then(ListInitialDatas, cantLoadInitialDatas);
|
||||
|
||||
|
||||
function ListInitialDatas(response) {
|
||||
$scope.cyberpanelLoading = true;
|
||||
if (response.data.status === 1) {
|
||||
$scope.records = JSON.parse(response.data.data);
|
||||
var parsed = JSON.parse(response.data.data);
|
||||
|
||||
for (var j = 0; j < parsed.length; j++) {
|
||||
websitesToBeBackedTemp.push(parsed[j].website);
|
||||
}
|
||||
} else {
|
||||
new PNotify({
|
||||
title: 'Operation Failed!',
|
||||
text: response.data.error_message,
|
||||
type: 'error'
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function cantLoadInitialDatas(response) {
|
||||
$scope.cyberpanelLoading = true;
|
||||
new PNotify({
|
||||
title: 'Operation Failed!',
|
||||
text: 'Could not connect to server, please refresh this page',
|
||||
type: 'error'
|
||||
});
|
||||
}
|
||||
|
||||
};
|
||||
$scope.populateCurrentRecords();
|
||||
|
||||
$scope.delSchedule = function (id) {
|
||||
|
||||
$scope.cyberpanelLoading = false;
|
||||
|
||||
url = "/IncrementalBackups/scheduleDelete";
|
||||
|
||||
|
||||
var data = {id: id};
|
||||
|
||||
var config = {
|
||||
headers: {
|
||||
'X-CSRFToken': getCookie('csrftoken')
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
$http.post(url, data, config).then(ListInitialDatas, cantLoadInitialDatas);
|
||||
|
||||
|
||||
function ListInitialDatas(response) {
|
||||
$scope.cyberpanelLoading = true;
|
||||
|
||||
if (response.data.status === 1) {
|
||||
$scope.populateCurrentRecords();
|
||||
} else {
|
||||
new PNotify({
|
||||
title: 'Operation Failed!',
|
||||
text: response.data.error_message,
|
||||
type: 'error'
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function cantLoadInitialDatas(response) {
|
||||
$scope.cyberpanelLoading = true;
|
||||
new PNotify({
|
||||
title: 'Operation Failed!',
|
||||
text: 'Could not connect to server, please refresh this page',
|
||||
type: 'error'
|
||||
});
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
});
|
||||
@@ -17,10 +17,10 @@
|
||||
<p>{% trans "On this page you can schedule Back ups to localhost or remote server (If you have added one)." %}</p>
|
||||
</div>
|
||||
|
||||
<div ng-controller="scheduleBackup" class="panel">
|
||||
<div ng-controller="scheduleBackupInc" class="panel">
|
||||
<div class="panel-body">
|
||||
<h3 class="title-hero">
|
||||
{% trans "Schedule Back up" %} <img ng-hide="scheduleBackupLoading"
|
||||
{% trans "Schedule Back up" %} <img ng-hide="cyberpanelLoading"
|
||||
src="{% static 'images/loading.gif' %}">
|
||||
</h3>
|
||||
<div class="example-box-wrapper">
|
||||
@@ -50,17 +50,48 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div ng-hide="localPath" class="form-group">
|
||||
<label class="col-sm-3 control-label">{% trans "Local Path" %}</label>
|
||||
<div class="col-sm-6">
|
||||
<input name="dom" type="text" class="form-control" ng-model="localPathValue"
|
||||
placeholder="{% trans "Local directory where backups will be moved after creation." %}"
|
||||
required>
|
||||
<div ng-hide="scheduleFreq" class="form-group">
|
||||
<label class="col-sm-3 control-label">{% trans "Backup Content" %}</label>
|
||||
<div class="col-sm-9">
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input ng-model="websiteData" type="checkbox" value="">
|
||||
Data
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<label class="col-sm-3 control-label"></label>
|
||||
<div class="col-sm-9">
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input ng-model="websiteDatabases" type="checkbox" value="">
|
||||
Databases
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<label class="col-sm-3 control-label"></label>
|
||||
<div class="col-sm-9">
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input ng-model="websiteEmails" type="checkbox" value="">
|
||||
Emails
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<!---
|
||||
<label class="col-sm-3 control-label"></label>
|
||||
<div class="col-sm-9">
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input ng-model="websiteSSLs" type="checkbox" value="">
|
||||
SSL Certificates
|
||||
</label>
|
||||
</div>
|
||||
</div> -->
|
||||
</div>
|
||||
|
||||
|
||||
<div ng-hide="scheduleBtn" class="form-group">
|
||||
<div ng-hide="scheduleFreq" class="form-group">
|
||||
<label class="col-sm-3 control-label"></label>
|
||||
<div class="col-sm-4">
|
||||
<button type="button" ng-click="addSchedule()"
|
||||
@@ -72,25 +103,42 @@
|
||||
|
||||
<!------ List of Destinations --------------->
|
||||
|
||||
<!------ List of Accounts --------------->
|
||||
|
||||
<div class="form-group">
|
||||
<div ng-hide="scheduleFreq" class="form-group">
|
||||
|
||||
<label class="col-sm-3 control-label"></label>
|
||||
<div class="col-sm-4">
|
||||
|
||||
<div ng-hide="canNotAddSchedule" class="alert alert-danger">
|
||||
<p>{% trans "Cannot add schedule. Error message:" %} {$ errorMessage $} </p>
|
||||
</div>
|
||||
|
||||
<div ng-hide="scheduleAdded" class="alert alert-success">
|
||||
<p>{% trans "Schedule Added" %}</p>
|
||||
</div>
|
||||
|
||||
<div ng-hide="couldNotConnect" class="alert alert-danger">
|
||||
<p>{% trans "Could not connect to server. Please refresh this page." %}</p>
|
||||
<div class="col-sm-12">
|
||||
<input type="text" ng-model="accountsSearch"
|
||||
placeholder="{% trans 'Search Accounts..' %}"
|
||||
class="form-control autocomplete-input">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div ng-hide="scheduleFreq" class="form-group">
|
||||
|
||||
<div class="col-sm-12">
|
||||
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{% trans "Select sites to be included in this job" %}</th>
|
||||
<th><input ng-model="webSiteStatus" ng-change="allChecked(webSiteStatus)"
|
||||
type="checkbox" value=""></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr ng-repeat="web in WebSitesList | filter:accountsSearch">
|
||||
<td ng-bind="web.domain"></td>
|
||||
<td ng-click=""><input ng-model="webSiteStatus"
|
||||
ng-change="addRemoveWebsite(web.domain,webSiteStatus)"
|
||||
type="checkbox" value=""></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!------ List of Accounts --------------->
|
||||
|
||||
<div class="form-group">
|
||||
|
||||
@@ -108,9 +156,9 @@
|
||||
<tbody>
|
||||
<tr ng-repeat="record in records track by $index">
|
||||
<td ng-bind="record.id"></td>
|
||||
<td ng-bind="record.destLoc"></td>
|
||||
<td ng-bind="record.destination"></td>
|
||||
<td ng-bind="record.frequency"></td>
|
||||
<td ng-click="delSchedule(record.destLoc,record.frequency)"><img
|
||||
<td ng-click="delSchedule(record.id)"><img
|
||||
src="{% static 'images/delete.png' %}"></td>
|
||||
|
||||
</tr>
|
||||
|
||||
@@ -14,4 +14,7 @@ urlpatterns = [
|
||||
url(r'^fetchRestorePoints$', views.fetchRestorePoints, name='fetchRestorePointsInc'),
|
||||
url(r'^restorePoint$', views.restorePoint, name='restorePointInc'),
|
||||
url(r'^scheduleBackups$', views.scheduleBackups, name='scheduleBackupsInc'),
|
||||
url(r'^submitBackupSchedule$', views.submitBackupSchedule, name='submitBackupScheduleInc'),
|
||||
url(r'^scheduleDelete$', views.scheduleDelete, name='scheduleDeleteInc'),
|
||||
url(r'^getCurrentBackupSchedules$', views.getCurrentBackupSchedules, name='getCurrentBackupSchedulesInc'),
|
||||
]
|
||||
@@ -10,7 +10,7 @@ import json
|
||||
import os
|
||||
from loginSystem.models import Administrator
|
||||
from websiteFunctions.models import Websites
|
||||
from .models import IncJob, JobSnapshots
|
||||
from .models import IncJob, BackupJob, JobSites
|
||||
from .IncBackupsControl import IncJobs
|
||||
from random import randint
|
||||
import time
|
||||
@@ -39,6 +39,8 @@ def createBackup(request):
|
||||
for items in os.listdir(path):
|
||||
destinations.append('sftp:%s' % (items))
|
||||
|
||||
path = '/home/cyberpanel/aws'
|
||||
|
||||
for items in os.listdir(path):
|
||||
destinations.append('s3:s3.amazonaws.com/%s' % (items))
|
||||
|
||||
@@ -563,6 +565,112 @@ def scheduleBackups(request):
|
||||
for items in os.listdir(path):
|
||||
destinations.append('s3:s3.amazonaws.com/%s' % (items))
|
||||
|
||||
return defRenderer(request, 'IncBackups/scheduleBackups.html', {'websiteList': websitesName, 'destinations': destinations})
|
||||
return defRenderer(request, 'IncBackups/backupSchedule.html', {'websiteList': websitesName, 'destinations': destinations})
|
||||
except BaseException, msg:
|
||||
return HttpResponse(str(msg))
|
||||
|
||||
def submitBackupSchedule(request):
|
||||
try:
|
||||
userID = request.session['userID']
|
||||
currentACL = ACLManager.loadedACL(userID)
|
||||
|
||||
if ACLManager.currentContextPermission(currentACL, 'scheDuleBackups') == 0:
|
||||
return ACLManager.loadErrorJson('scheduleStatus', 0)
|
||||
|
||||
data = json.loads(request.body)
|
||||
|
||||
backupDest = data['backupDestinations']
|
||||
backupFreq = data['backupFreq']
|
||||
websitesToBeBacked = data['websitesToBeBacked']
|
||||
|
||||
try:
|
||||
websiteData = data['websiteData']
|
||||
websiteData = 1
|
||||
except:
|
||||
websiteData = False
|
||||
websiteData = 0
|
||||
|
||||
try:
|
||||
websiteEmails = data['websiteEmails']
|
||||
websiteEmails = 1
|
||||
except:
|
||||
websiteEmails = False
|
||||
websiteEmails = 0
|
||||
|
||||
try:
|
||||
websiteDatabases = data['websiteDatabases']
|
||||
websiteDatabases = 1
|
||||
except:
|
||||
websiteDatabases = False
|
||||
websiteDatabases = 0
|
||||
|
||||
newJob = BackupJob(websiteData=websiteData, websiteDataEmails=websiteEmails, websiteDatabases=websiteDatabases, destination=backupDest, frequency=backupFreq)
|
||||
newJob.save()
|
||||
|
||||
for items in websitesToBeBacked:
|
||||
jobsite = JobSites(job=newJob, website=items)
|
||||
jobsite.save()
|
||||
|
||||
final_json = json.dumps({'status': 1, 'error_message': "None"})
|
||||
return HttpResponse(final_json)
|
||||
|
||||
|
||||
except BaseException, msg:
|
||||
final_json = json.dumps({'status': 0, 'error_message': str(msg)})
|
||||
return HttpResponse(final_json)
|
||||
|
||||
def getCurrentBackupSchedules(request):
|
||||
try:
|
||||
userID = request.session['userID']
|
||||
currentACL = ACLManager.loadedACL(userID)
|
||||
|
||||
if ACLManager.currentContextPermission(currentACL, 'scheDuleBackups') == 0:
|
||||
return ACLManager.loadErrorJson('fetchStatus', 0)
|
||||
|
||||
records = BackupJob.objects.all()
|
||||
|
||||
json_data = "["
|
||||
checker = 0
|
||||
|
||||
for items in records:
|
||||
dic = {'id': items.id,
|
||||
'destination': items.destination,
|
||||
'frequency': items.frequency,
|
||||
}
|
||||
|
||||
if checker == 0:
|
||||
json_data = json_data + json.dumps(dic)
|
||||
checker = 1
|
||||
else:
|
||||
json_data = json_data + ',' + json.dumps(dic)
|
||||
|
||||
json_data = json_data + ']'
|
||||
final_json = json.dumps({'status': 1, 'error_message': "None", "data": json_data})
|
||||
return HttpResponse(final_json)
|
||||
|
||||
except BaseException, msg:
|
||||
final_dic = {'status': 0, 'error_message': str(msg)}
|
||||
final_json = json.dumps(final_dic)
|
||||
return HttpResponse(final_json)
|
||||
|
||||
def scheduleDelete(request):
|
||||
try:
|
||||
userID = request.session['userID']
|
||||
currentACL = ACLManager.loadedACL(userID)
|
||||
|
||||
if ACLManager.currentContextPermission(currentACL, 'scheDuleBackups') == 0:
|
||||
return ACLManager.loadErrorJson('scheduleStatus', 0)
|
||||
|
||||
data = json.loads(request.body)
|
||||
|
||||
id = data['id']
|
||||
|
||||
backupJob = BackupJob.objects.get(id=id)
|
||||
backupJob.delete()
|
||||
|
||||
final_json = json.dumps({'status': 1, 'error_message': "None"})
|
||||
return HttpResponse(final_json)
|
||||
|
||||
except BaseException, msg:
|
||||
final_json = json.dumps({'status': 0, 'error_message': str(msg)})
|
||||
return HttpResponse(final_json)
|
||||
0
plogical/csf.py
Normal file → Executable file
0
plogical/csf.py
Normal file → Executable file
@@ -249,6 +249,7 @@ password=%s
|
||||
return 1
|
||||
except BaseException, msg:
|
||||
logging.CyberCPLogFileWriter.writeToFile(str(msg) + "[restoreDatabaseBackup]")
|
||||
return 0
|
||||
|
||||
@staticmethod
|
||||
def submitDBCreation(dbName, dbUsername, dbPassword, databaseWebsite):
|
||||
|
||||
@@ -5,6 +5,7 @@ import os
|
||||
import socket
|
||||
import threading as multi
|
||||
import time
|
||||
import getpass
|
||||
|
||||
class ProcessUtilities(multi.Thread):
|
||||
litespeedProcess = "litespeed"
|
||||
@@ -216,6 +217,10 @@ class ProcessUtilities(multi.Thread):
|
||||
@staticmethod
|
||||
def executioner(command, user=None):
|
||||
try:
|
||||
if getpass.getuser() == 'root':
|
||||
ProcessUtilities.normalExecutioner(command)
|
||||
return 1
|
||||
|
||||
ret = ProcessUtilities.sendCommand(command, user)
|
||||
|
||||
exitCode = ret[len(ret) -1]
|
||||
@@ -235,6 +240,9 @@ class ProcessUtilities(multi.Thread):
|
||||
@staticmethod
|
||||
def outputExecutioner(command, user=None):
|
||||
try:
|
||||
if getpass.getuser() == 'root':
|
||||
return subprocess.check_output(shlex.split(command))
|
||||
|
||||
if type(command) == str or type(command) == unicode:
|
||||
pass
|
||||
else:
|
||||
|
||||
7
serverLogs/views.py
Normal file → Executable file
7
serverLogs/views.py
Normal file → Executable file
@@ -12,7 +12,6 @@ import shlex
|
||||
from plogical.virtualHostUtilities import virtualHostUtilities
|
||||
from plogical.acl import ACLManager
|
||||
from plogical.processUtilities import ProcessUtilities
|
||||
import os
|
||||
# Create your views here.
|
||||
|
||||
|
||||
@@ -131,15 +130,9 @@ def getLogsFromFile(request):
|
||||
elif type == "error":
|
||||
fileName = installUtilities.Server_root_path + "/logs/error.log"
|
||||
elif type == "email":
|
||||
if ProcessUtilities.decideDistro() == ProcessUtilities.centos:
|
||||
fileName = "/var/log/maillog"
|
||||
else:
|
||||
fileName = "/var/log/mail.log"
|
||||
elif type == "ftp":
|
||||
if ProcessUtilities.decideDistro() == ProcessUtilities.centos:
|
||||
fileName = "/var/log/messages"
|
||||
else:
|
||||
fileName = "/var/log/syslog"
|
||||
elif type == "modSec":
|
||||
fileName = "/usr/local/lsws/logs/auditmodsec.log"
|
||||
elif type == "cyberpanel":
|
||||
|
||||
Reference in New Issue
Block a user