incremental backups: completion and s3:aws integration

This commit is contained in:
Usman Nasir
2019-10-14 17:40:58 +05:00
parent 53c5536f0f
commit eaee1bcac2
16 changed files with 1851 additions and 46 deletions

31
.idea/CyberCP.iml generated Executable file
View 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="&lt;map/&gt;" />
<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
View 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
View 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

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,7 @@
from plogical.CyberCPLogFileWriter import CyberCPLogFileWriter as logging from plogical.CyberCPLogFileWriter import CyberCPLogFileWriter as logging
import json import json
from django.shortcuts import HttpResponse from django.shortcuts import HttpResponse
import re
class secMiddleware: class secMiddleware:
@@ -58,6 +59,14 @@ class secMiddleware:
else: else:
continue 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: 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 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': 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':

View File

@@ -52,6 +52,42 @@ class IncJobs(multi.Thread):
elif self.function == 'restorePoint': elif self.function == 'restorePoint':
self.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): def restoreData(self):
try: 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) 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) result = ProcessUtilities.outputExecutioner(command)
logging.statusWriter(self.statusPath, result, 1) logging.statusWriter(self.statusPath, result, 1)
else:
self.awsFunction('restore', '', self.jobid.snapshotid)
except BaseException, msg: except BaseException, msg:
logging.statusWriter(self.statusPath, "%s [46][5009]" % (str(msg)), 1) 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) 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) result = ProcessUtilities.outputExecutioner(command)
logging.statusWriter(self.statusPath, result, 1) 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 raise BaseException
try: 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) 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) result = ProcessUtilities.outputExecutioner(command)
logging.statusWriter(self.statusPath, result, 1) logging.statusWriter(self.statusPath, result, 1)
else:
self.awsFunction('restore', '', self.jobid.snapshotid)
except BaseException, msg: except BaseException, msg:
logging.statusWriter(self.statusPath, "%s [46][5009]" % (str(msg)), 1) 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, newSnapshot = JobSnapshots(job=self.jobid, type='data:%s' % (remotePath), snapshotid=snapShotid,
destination=self.backupDestinations) destination=self.backupDestinations)
newSnapshot.save() 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) logging.statusWriter(self.statusPath, 'Data for %s backed to %s.' % (self.website.domain, self.backupDestinations), 1)
return 1 return 1
@@ -402,6 +447,8 @@ class IncJobs(multi.Thread):
newSnapshot = JobSnapshots(job=self.jobid, type='database:%s' % (items.dbName), snapshotid=snapShotid, newSnapshot = JobSnapshots(job=self.jobid, type='database:%s' % (items.dbName), snapshotid=snapShotid,
destination=self.backupDestinations) destination=self.backupDestinations)
newSnapshot.save() newSnapshot.save()
else:
self.awsFunction('backup', dbPath, '', 'database')
try: try:
os.remove('/home/cyberpanel/%s' % (items.dbName)) 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, newSnapshot = JobSnapshots(job=self.jobid, type='email:%s' % (backupPath), snapshotid=snapShotid,
destination=self.backupDestinations) destination=self.backupDestinations)
newSnapshot.save() newSnapshot.save()
else:
self.awsFunction('backup', backupPath, '', 'email')
logging.statusWriter(self.statusPath, 'Emails for %s backed to %s.' % (self.website.domain, self.backupDestinations), 1) 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) result = ProcessUtilities.outputExecutioner(command)
logging.statusWriter(self.statusPath, result, 1) logging.statusWriter(self.statusPath, result, 1)
else: else:
logging.statusWriter(self.statusPath, 'AWS implementation is currently pending. [5009]', 1) key,secret = self.getAWSData()
return 0 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) logging.statusWriter(self.statusPath, 'Repo %s initiated for %s.' % (self.backupDestinations, self.website.domain), 1)
return 1 return 1

View 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()

View File

@@ -13,3 +13,18 @@ class JobSnapshots(models.Model):
type = models.CharField(max_length=300) type = models.CharField(max_length=300)
snapshotid = models.CharField(max_length=50) snapshotid = models.CharField(max_length=50)
destination = models.CharField(max_length=200, default='') 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)

View File

@@ -156,7 +156,8 @@ app.controller('createIncrementalBackups', function ($scope, $http, $timeout) {
if (response.data.status === 1) { if (response.data.status === 1) {
$scope.tempPath = response.data.tempPath; $scope.tempPath = response.data.tempPath;
getBackupStatus(); getBackupStatus();
}else{ } else {
$scope.cyberpanelLoading = true;
new PNotify({ new PNotify({
title: 'Operation Failed!', title: 'Operation Failed!',
text: response.data.error_message, text: response.data.error_message,
@@ -198,7 +199,7 @@ app.controller('createIncrementalBackups', function ($scope, $http, $timeout) {
$scope.populateCurrentRecords(); $scope.populateCurrentRecords();
}else{ } else {
new PNotify({ new PNotify({
title: 'Operation Failed!', title: 'Operation Failed!',
text: response.data.error_message, text: response.data.error_message,
@@ -273,7 +274,7 @@ app.controller('createIncrementalBackups', function ($scope, $http, $timeout) {
var data = { var data = {
websiteToBeBacked: $scope.websiteToBeBacked, websiteToBeBacked: $scope.websiteToBeBacked,
jobid : id, jobid: id,
reconstruct: reconstruct reconstruct: reconstruct
}; };
@@ -317,6 +318,7 @@ app.controller('incrementalDestinations', function ($scope, $http) {
if ($scope.destinationType === 'SFTP') { if ($scope.destinationType === 'SFTP') {
$scope.sftpHide = false; $scope.sftpHide = false;
$scope.awsHide = true;
$scope.populateCurrentRecords(); $scope.populateCurrentRecords();
} else { } else {
$scope.sftpHide = true; $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'
});
}
};
});

View File

@@ -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> <p>{% trans "On this page you can schedule Back ups to localhost or remote server (If you have added one)." %}</p>
</div> </div>
<div ng-controller="scheduleBackup" class="panel"> <div ng-controller="scheduleBackupInc" class="panel">
<div class="panel-body"> <div class="panel-body">
<h3 class="title-hero"> <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' %}"> src="{% static 'images/loading.gif' %}">
</h3> </h3>
<div class="example-box-wrapper"> <div class="example-box-wrapper">
@@ -50,17 +50,48 @@
</div> </div>
</div> </div>
<div ng-hide="localPath" class="form-group"> <div ng-hide="scheduleFreq" class="form-group">
<label class="col-sm-3 control-label">{% trans "Local Path" %}</label> <label class="col-sm-3 control-label">{% trans "Backup Content" %}</label>
<div class="col-sm-6"> <div class="col-sm-9">
<input name="dom" type="text" class="form-control" ng-model="localPathValue" <div class="checkbox">
placeholder="{% trans "Local directory where backups will be moved after creation." %}" <label>
required> <input ng-model="websiteData" type="checkbox" value="">
Data
</label>
</div> </div>
</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> <label class="col-sm-3 control-label"></label>
<div class="col-sm-4"> <div class="col-sm-4">
<button type="button" ng-click="addSchedule()" <button type="button" ng-click="addSchedule()"
@@ -72,25 +103,42 @@
<!------ List of Destinations ---------------> <!------ 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-12">
<div class="col-sm-4"> <input type="text" ng-model="accountsSearch"
placeholder="{% trans 'Search Accounts..' %}"
<div ng-hide="canNotAddSchedule" class="alert alert-danger"> class="form-control autocomplete-input">
<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> </div>
</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>
</div>
<!------ List of Accounts --------------->
<div class="form-group"> <div class="form-group">
@@ -108,9 +156,9 @@
<tbody> <tbody>
<tr ng-repeat="record in records track by $index"> <tr ng-repeat="record in records track by $index">
<td ng-bind="record.id"></td> <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-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> src="{% static 'images/delete.png' %}"></td>
</tr> </tr>

View File

@@ -14,4 +14,7 @@ urlpatterns = [
url(r'^fetchRestorePoints$', views.fetchRestorePoints, name='fetchRestorePointsInc'), url(r'^fetchRestorePoints$', views.fetchRestorePoints, name='fetchRestorePointsInc'),
url(r'^restorePoint$', views.restorePoint, name='restorePointInc'), url(r'^restorePoint$', views.restorePoint, name='restorePointInc'),
url(r'^scheduleBackups$', views.scheduleBackups, name='scheduleBackupsInc'), 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'),
] ]

View File

@@ -10,7 +10,7 @@ import json
import os import os
from loginSystem.models import Administrator from loginSystem.models import Administrator
from websiteFunctions.models import Websites from websiteFunctions.models import Websites
from .models import IncJob, JobSnapshots from .models import IncJob, BackupJob, JobSites
from .IncBackupsControl import IncJobs from .IncBackupsControl import IncJobs
from random import randint from random import randint
import time import time
@@ -39,6 +39,8 @@ def createBackup(request):
for items in os.listdir(path): for items in os.listdir(path):
destinations.append('sftp:%s' % (items)) destinations.append('sftp:%s' % (items))
path = '/home/cyberpanel/aws'
for items in os.listdir(path): for items in os.listdir(path):
destinations.append('s3:s3.amazonaws.com/%s' % (items)) destinations.append('s3:s3.amazonaws.com/%s' % (items))
@@ -563,6 +565,112 @@ def scheduleBackups(request):
for items in os.listdir(path): for items in os.listdir(path):
destinations.append('s3:s3.amazonaws.com/%s' % (items)) 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: except BaseException, msg:
return HttpResponse(str(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
View File

View File

@@ -249,6 +249,7 @@ password=%s
return 1 return 1
except BaseException, msg: except BaseException, msg:
logging.CyberCPLogFileWriter.writeToFile(str(msg) + "[restoreDatabaseBackup]") logging.CyberCPLogFileWriter.writeToFile(str(msg) + "[restoreDatabaseBackup]")
return 0
@staticmethod @staticmethod
def submitDBCreation(dbName, dbUsername, dbPassword, databaseWebsite): def submitDBCreation(dbName, dbUsername, dbPassword, databaseWebsite):

View File

@@ -5,6 +5,7 @@ import os
import socket import socket
import threading as multi import threading as multi
import time import time
import getpass
class ProcessUtilities(multi.Thread): class ProcessUtilities(multi.Thread):
litespeedProcess = "litespeed" litespeedProcess = "litespeed"
@@ -216,6 +217,10 @@ class ProcessUtilities(multi.Thread):
@staticmethod @staticmethod
def executioner(command, user=None): def executioner(command, user=None):
try: try:
if getpass.getuser() == 'root':
ProcessUtilities.normalExecutioner(command)
return 1
ret = ProcessUtilities.sendCommand(command, user) ret = ProcessUtilities.sendCommand(command, user)
exitCode = ret[len(ret) -1] exitCode = ret[len(ret) -1]
@@ -235,6 +240,9 @@ class ProcessUtilities(multi.Thread):
@staticmethod @staticmethod
def outputExecutioner(command, user=None): def outputExecutioner(command, user=None):
try: try:
if getpass.getuser() == 'root':
return subprocess.check_output(shlex.split(command))
if type(command) == str or type(command) == unicode: if type(command) == str or type(command) == unicode:
pass pass
else: else:

7
serverLogs/views.py Normal file → Executable file
View File

@@ -12,7 +12,6 @@ import shlex
from plogical.virtualHostUtilities import virtualHostUtilities from plogical.virtualHostUtilities import virtualHostUtilities
from plogical.acl import ACLManager from plogical.acl import ACLManager
from plogical.processUtilities import ProcessUtilities from plogical.processUtilities import ProcessUtilities
import os
# Create your views here. # Create your views here.
@@ -131,15 +130,9 @@ def getLogsFromFile(request):
elif type == "error": elif type == "error":
fileName = installUtilities.Server_root_path + "/logs/error.log" fileName = installUtilities.Server_root_path + "/logs/error.log"
elif type == "email": elif type == "email":
if ProcessUtilities.decideDistro() == ProcessUtilities.centos:
fileName = "/var/log/maillog" fileName = "/var/log/maillog"
else:
fileName = "/var/log/mail.log"
elif type == "ftp": elif type == "ftp":
if ProcessUtilities.decideDistro() == ProcessUtilities.centos:
fileName = "/var/log/messages" fileName = "/var/log/messages"
else:
fileName = "/var/log/syslog"
elif type == "modSec": elif type == "modSec":
fileName = "/usr/local/lsws/logs/auditmodsec.log" fileName = "/usr/local/lsws/logs/auditmodsec.log"
elif type == "cyberpanel": elif type == "cyberpanel":