push changes

This commit is contained in:
Michael Ramsey 2019-10-08 10:53:02 -04:00
parent 0695e9c9d0
commit bd71b39d31
1802 changed files with 170876 additions and 50904 deletions

7
.gitignore vendored Normal file
View File

@ -0,0 +1,7 @@
*.pyc
ApachController/
0*.py
bin/
lib/
share/
public/

31
.idea/CyberCP.iml Normal 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 Normal 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 Normal 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>

1073
.idea/workspace.xml Normal file

File diff suppressed because it is too large Load Diff

191
CLManager/CLManagerMain.py Normal file
View File

@ -0,0 +1,191 @@
import threading as multi
from plogical.acl import ACLManager
import plogical.CyberCPLogFileWriter as logging
from plogical.processUtilities import ProcessUtilities
from django.shortcuts import render
import os
from serverStatus.serverStatusUtil import ServerStatusUtil
import json
from django.shortcuts import HttpResponse
from math import ceil
from websiteFunctions.models import Websites
from .models import CLPackages
class CLManagerMain(multi.Thread):
def __init__(self, request=None, templateName=None, function=None, data=None):
multi.Thread.__init__(self)
self.request = request
self.templateName = templateName
self.function = function
self.data = data
def run(self):
try:
if self.function == 'submitCageFSInstall':
self.submitCageFSInstall()
elif self.function == 'enableOrDisable':
self.enableOrDisable()
except BaseException, msg:
logging.CyberCPLogFileWriter.writeToFile(str(msg) + ' [ContainerManager.run]')
def renderC(self):
userID = self.request.session['userID']
currentACL = ACLManager.loadedACL(userID)
if currentACL['admin'] == 1:
pass
else:
return ACLManager.loadError()
data = {}
data['CL'] = 0
data['CAGEFS'] = 0
CLPath = '/etc/sysconfig/cloudlinux'
CageFSPath = '/usr/sbin/cagefsctl'
if os.path.exists(CLPath):
data['CL'] = 1
if os.path.exists(CageFSPath):
data['CAGEFS'] = 1
if data['CL'] == 0:
return render(self.request, 'CLManager/notAvailable.html', data)
elif data['CAGEFS'] == 0:
return render(self.request, 'CLManager/notAvailable.html', data)
else:
return render(self.request, self.templateName, self.data)
def submitCageFSInstall(self):
try:
userID = self.request.session['userID']
currentACL = ACLManager.loadedACL(userID)
if currentACL['admin'] == 1:
pass
else:
logging.CyberCPLogFileWriter.statusWriter(ServerStatusUtil.lswsInstallStatusPath,
'Not authorized to install container packages. [404].',
1)
return 0
execPath = "/usr/local/CyberCP/bin/python2 /usr/local/CyberCP/CLManager/CageFS.py"
execPath = execPath + " --function submitCageFSInstall"
ProcessUtilities.outputExecutioner(execPath)
except BaseException, msg:
logging.CyberCPLogFileWriter.statusWriter(ServerStatusUtil.lswsInstallStatusPath, str(msg) + ' [404].', 1)
def findWebsitesJson(self, currentACL, userID, pageNumber):
finalPageNumber = ((pageNumber * 10)) - 10
endPageNumber = finalPageNumber + 10
websites = ACLManager.findWebsiteObjects(currentACL, userID)[finalPageNumber:endPageNumber]
json_data = "["
checker = 0
command = '/usr/sbin/cagefsctl --list-enabled'
Enabled = ProcessUtilities.outputExecutioner(command)
for items in websites:
if Enabled.find(items.externalApp) > -1:
status = 1
else:
status = 0
dic = {'domain': items.domain, 'externalApp': items.externalApp, 'status': status}
if checker == 0:
json_data = json_data + json.dumps(dic)
checker = 1
else:
json_data = json_data + ',' + json.dumps(dic)
json_data = json_data + ']'
return json_data
def websitePagination(self, currentACL, userID):
websites = ACLManager.findAllSites(currentACL, userID)
pages = float(len(websites)) / float(10)
pagination = []
if pages <= 1.0:
pages = 1
pagination.append('<li><a href="\#"></a></li>')
else:
pages = ceil(pages)
finalPages = int(pages) + 1
for i in range(1, finalPages):
pagination.append('<li><a href="\#">' + str(i) + '</a></li>')
return pagination
def getFurtherAccounts(self, userID=None, data=None):
try:
currentACL = ACLManager.loadedACL(userID)
pageNumber = int(data['page'])
json_data = self.findWebsitesJson(currentACL, userID, pageNumber)
pagination = self.websitePagination(currentACL, userID)
cageFSPath = '/home/cyberpanel/cagefs'
if os.path.exists(cageFSPath):
default = 'On'
else:
default = 'Off'
final_dic = {'status': 1, 'listWebSiteStatus': 1, 'error_message': "None", "data": json_data,
'pagination': pagination, 'default': default}
final_json = json.dumps(final_dic)
return HttpResponse(final_json)
except BaseException, msg:
dic = {'status': 1, 'listWebSiteStatus': 0, 'error_message': str(msg)}
json_data = json.dumps(dic)
return HttpResponse(json_data)
def enableOrDisable(self):
try:
websites = Websites.objects.all()
if self.data['mode'] == 1:
for items in websites:
command = '/usr/sbin/cagefsctl --enable %s' % (items.externalApp)
ProcessUtilities.executioner(command)
else:
for items in websites:
command = '/usr/sbin/cagefsctl --disable %s' % (items.externalApp)
ProcessUtilities.executioner(command)
except BaseException, msg:
logging.CyberCPLogFileWriter.writeToFile(str(msg))
def fetchPackages(self, currentACL):
if currentACL['admin'] == 1:
pass
else:
return ACLManager.loadErrorJson()
json_data = "["
checker = 0
for items in CLPackages.objects.all():
dic = {'name': items.name, 'SPEED': items.speed, 'VMEM': items.vmem, 'PMEM': items.pmem, 'IO': items.io, 'IOPS': items.iops, 'EP': items.ep,
'NPROC': items.nproc, 'inodessoft': items.inodessoft, 'inodeshard': items.inodeshard}
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_dic = {'status': 1, 'error_message': "None", "data": json_data}
final_json = json.dumps(final_dic)
return HttpResponse(final_json)

82
CLManager/CLPackages.py Normal file
View File

@ -0,0 +1,82 @@
#!/usr/local/CyberCP/bin/python2
import os
import os.path
import sys
import django
sys.path.append('/usr/local/CyberCP')
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "CyberCP.settings")
django.setup()
import argparse
from websiteFunctions.models import Websites
from CLManager.models import CLPackages
import pwd
class CLinuxPackages:
@staticmethod
def listAll():
for items in Websites.objects.all():
itemPackage = items.package
try:
clPackage = CLPackages.objects.get(owner=itemPackage)
statement = '%s %s' % (pwd.getpwnam(items.externalApp).pw_uid, clPackage.name)
print statement
except:
pass
@staticmethod
def listPackages():
for items in CLPackages.objects.all():
print items.name
@staticmethod
def userIDPackage(user):
website = Websites.objects.get(externalApp=user)
itemPackage = website.package
try:
clPackage = CLPackages.objects.get(owner=itemPackage)
print clPackage
except:
pass
@staticmethod
def packageForUser(package):
for items in Websites.objects.all():
itemPackage = items.package
try:
clPackage = CLPackages.objects.get(owner=itemPackage)
if clPackage.name == package:
print pwd.getpwnam(items.externalApp).pw_uid
except:
pass
def main():
parser = argparse.ArgumentParser(description='CyberPanel Container Manager')
parser.add_argument('--userid', help='User ID')
parser.add_argument('--package', help='Package')
parser.add_argument('--function', help='Function')
parser.add_argument('--list-all', help='List all users/packages.', action='store_true')
parser.add_argument('--list-packages', help='List all packages.', action='store_true')
args = vars(parser.parse_args())
if args['userid']:
CLinuxPackages.userIDPackage(args['userid'])
elif args['package']:
CLinuxPackages.packageForUser(args['package'])
elif args['list_all']:
CLinuxPackages.listAll()
elif args['list_packages']:
CLinuxPackages.listPackages()
if __name__ == "__main__":
main()

60
CLManager/CageFS.py Normal file
View File

@ -0,0 +1,60 @@
#!/usr/local/CyberCP/bin/python2
import sys
sys.path.append('/usr/local/CyberCP')
import plogical.CyberCPLogFileWriter as logging
import argparse
from plogical.mailUtilities import mailUtilities
from serverStatus.serverStatusUtil import ServerStatusUtil
class CageFS:
packages = ['talksho']
users = ['5001']
@staticmethod
def submitCageFSInstall():
try:
mailUtilities.checkHome()
statusFile = open(ServerStatusUtil.lswsInstallStatusPath, 'w')
logging.CyberCPLogFileWriter.statusWriter(ServerStatusUtil.lswsInstallStatusPath,
"Starting Packages Installation..\n", 1)
command = 'sudo yum install cagefs -y'
ServerStatusUtil.executioner(command, statusFile)
command = 'sudo /usr/sbin/cagefsctl --init'
ServerStatusUtil.executioner(command, statusFile)
command = 'sudo /usr/sbin/cagefsctl --update-etc'
ServerStatusUtil.executioner(command, statusFile)
command = 'sudo /usr/sbin/cagefsctl --force-update'
ServerStatusUtil.executioner(command, statusFile)
logging.CyberCPLogFileWriter.statusWriter(ServerStatusUtil.lswsInstallStatusPath,
"Packages successfully installed.[200]\n", 1)
except BaseException, msg:
logging.CyberCPLogFileWriter.statusWriter(ServerStatusUtil.lswsInstallStatusPath, str(msg) + ' [404].', 1)
def main():
parser = argparse.ArgumentParser(description='CyberPanel CageFS Manager')
parser.add_argument('--function', help='Function')
args = vars(parser.parse_args())
if args["function"] == "submitCageFSInstall":
CageFS.submitCageFSInstall()
if __name__ == "__main__":
main()

0
CLManager/__init__.py Normal file
View File

6
CLManager/admin.py Normal file
View File

@ -0,0 +1,6 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.contrib import admin
# Register your models here.

8
CLManager/apps.py Normal file
View File

@ -0,0 +1,8 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.apps import AppConfig
class ClmanagerConfig(AppConfig):
name = 'CLManager'

View File

20
CLManager/models.py Normal file
View File

@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models
from packages.models import Package
# Create your models here.
class CLPackages(models.Model):
owner = models.ForeignKey(Package)
name = models.CharField(max_length=50,unique=True)
speed = models.CharField(max_length=50)
vmem = models.CharField(max_length=50)
pmem = models.CharField(max_length=50)
io = models.CharField(max_length=50)
iops = models.CharField(max_length=50)
ep = models.CharField(max_length=50)
nproc = models.CharField(max_length=50)
inodessoft = models.CharField(max_length=50)
inodeshard = models.CharField(max_length=50)

View File

@ -0,0 +1,934 @@
app.controller('installCageFS', function ($scope, $http, $timeout, $window) {
$scope.installDockerStatus = true;
$scope.installBoxGen = true;
$scope.dockerInstallBTN = false;
$scope.submitCageFSInstall = function () {
$scope.installDockerStatus = false;
$scope.installBoxGen = true;
$scope.dockerInstallBTN = true;
url = "/CloudLinux/submitCageFSInstall";
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.installBoxGen = false;
getRequestStatus();
} 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'
});
}
};
function getRequestStatus() {
$scope.cyberPanelLoading = false;
url = "/serverstatus/switchTOLSWSStatus";
var data = {};
var config = {
headers: {
'X-CSRFToken': getCookie('csrftoken')
}
};
$http.post(url, data, config).then(ListInitialDatas, cantLoadInitialDatas);
function ListInitialDatas(response) {
if (response.data.abort === 0) {
$scope.requestData = response.data.requestStatus;
$timeout(getRequestStatus, 1000);
} else {
// Notifications
$scope.cyberPanelLoading = true;
$timeout.cancel();
$scope.requestData = response.data.requestStatus;
if (response.data.installed === 1) {
$timeout(function () {
$window.location.reload();
}, 3000);
}
}
}
function cantLoadInitialDatas(response) {
$scope.cyberPanelLoading = true;
new PNotify({
title: 'Operation Failed!',
text: 'Could not connect to server, please refresh this page',
type: 'error'
});
}
}
});
app.controller('listWebsitesCage', function ($scope, $http) {
var globalPageNumber;
$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;
console.log("not good");
}
};
$scope.getFurtherWebsitesFromDB(1);
$scope.cyberPanelLoading = true;
$scope.searchWebsites = function () {
$scope.cyberPanelLoading = false;
var config = {
headers: {
'X-CSRFToken': getCookie('csrftoken')
}
};
var data = {
patternAdded: $scope.patternAdded
};
dataurl = "/websites/searchWebsites";
$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;
$("#listFail").hide();
} else {
new PNotify({
title: 'Operation Failed!',
text: response.data.error_message,
type: 'error'
});
}
}
function cantLoadInitialData(response) {
$scope.cyberPanelLoading = true;
new PNotify({
title: 'Operation Failed!',
text: 'Connect disrupted, refresh the page.',
type: 'error'
});
}
};
$scope.enableOrDisable = function (domain, all, mode, toggle = 0) {
$scope.cyberPanelLoading = false;
url = "/CloudLinux/enableOrDisable";
var data = {
domain: domain,
all: all,
mode: mode,
toggle: toggle
};
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) {
new PNotify({
title: 'Success',
text: response.data.success,
type: 'success'
});
if (all === 0) {
$scope.getFurtherWebsitesFromDB(globalPageNumber);
}
} 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.refreshStatus = function () {
$scope.getFurtherWebsitesFromDB(globalPageNumber);
}
});
app.controller('createCLPackage', function ($scope, $http) {
$scope.cyberPanelLoading = true;
$scope.modifyPackageForm = true;
$scope.toggleView = function () {
$scope.modifyPackageForm = false;
};
$scope.createPackage = function () {
$scope.cyberPanelLoading = false;
url = "/CloudLinux/submitCreatePackage";
var data = {
selectedPackage: $scope.selectedPackage,
name: $scope.name,
SPEED: $scope.SPEED,
VMEM: $scope.VMEM,
PMEM: $scope.PMEM,
IO: $scope.IO,
IOPS: $scope.IOPS,
EP: $scope.EP,
NPROC: $scope.NPROC,
INODESsoft: $scope.INODESsoft,
INODEShard: $scope.INODEShard,
};
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) {
new PNotify({
title: 'Success',
text: 'Successfully created.',
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'
});
}
};
});
app.controller('listCloudLinuxPackages', function ($scope, $http) {
$scope.cyberPanelLoading = true;
$scope.fetchPackageas = function () {
$scope.cyberPanelLoading = false;
var config = {
headers: {
'X-CSRFToken': getCookie('csrftoken')
}
};
var data = {};
dataurl = "/CloudLinux/fetchPackages";
$http.post(dataurl, data, config).then(ListInitialData, cantLoadInitialData);
function ListInitialData(response) {
$scope.cyberPanelLoading = true;
if (response.data.status === 1) {
$scope.packages = JSON.parse(response.data.data);
} else {
new PNotify({
title: 'Operation Failed!',
text: response.data.error_message,
type: 'error'
});
}
}
function cantLoadInitialData(response) {
$scope.cyberPanelLoading = true;
new PNotify({
title: 'Operation Failed!',
text: 'Could not connect to server, please refresh this page',
type: 'error'
});
}
};
$scope.fetchPackageas();
$scope.deleteCLPackage = function (name) {
$scope.cyberPanelLoading = false;
url = "/CloudLinux/deleteCLPackage";
var data = {
name: name
};
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) {
new PNotify({
title: 'Success',
text: 'Successfully deleted.',
type: 'success'
});
$scope.fetchPackageas();
} 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.populatePackage = function (name, speed, vmem, pmem, io, iops, ep, nproc, inodessoft, inodeshard) {
$scope.name = name;
$scope.SPEED = speed;
$scope.VMEM = vmem;
$scope.PMEM = pmem;
$scope.IO = io;
$scope.IOPS = iops;
$scope.EP = ep;
$scope.NPROC = nproc;
$scope.inodessoft = inodessoft;
$scope.inodeshard = inodeshard;
};
$scope.saveSettings = function () {
$scope.cyberPanelLoading = false;
url = "/CloudLinux/saveSettings";
var data = {
name: $scope.name,
SPEED: $scope.SPEED,
VMEM: $scope.VMEM,
PMEM: $scope.PMEM,
IO: $scope.IO,
IOPS: $scope.IOPS,
EP: $scope.EP,
NPROC: $scope.NPROC,
INODESsoft: $scope.inodessoft,
INODEShard: $scope.inodeshard,
};
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) {
new PNotify({
title: 'Success',
text: 'Changes successfully applied.',
type: 'success'
});
$scope.fetchPackageas();
} 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'
});
}
};
});
app.controller('websiteContainerLimitCL', function ($scope, $http, $timeout, $window) {
// Get CPU Usage of User
var cpu = [];
var dataset;
var totalPoints = 100;
var updateInterval = 1000;
var now = new Date().getTime();
var options = {
series: {
lines: {
lineWidth: 1.2
},
bars: {
align: "center",
fillColor: {colors: [{opacity: 1}, {opacity: 1}]},
barWidth: 500,
lineWidth: 1
}
},
xaxis: {
mode: "time",
tickSize: [5, "second"],
tickFormatter: function (v, axis) {
var date = new Date(v);
if (date.getSeconds() % 20 == 0) {
var hours = date.getHours() < 10 ? "0" + date.getHours() : date.getHours();
var minutes = date.getMinutes() < 10 ? "0" + date.getMinutes() : date.getMinutes();
var seconds = date.getSeconds() < 10 ? "0" + date.getSeconds() : date.getSeconds();
return hours + ":" + minutes + ":" + seconds;
} else {
return "";
}
},
axisLabel: "Time",
axisLabelUseCanvas: true,
axisLabelFontSizePixels: 12,
axisLabelFontFamily: 'Verdana, Arial',
axisLabelPadding: 10
},
yaxes: [
{
min: 0,
max: 100,
tickSize: 5,
tickFormatter: function (v, axis) {
if (v % 10 == 0) {
return v + "%";
} else {
return "";
}
},
axisLabel: "CPU loading",
axisLabelUseCanvas: true,
axisLabelFontSizePixels: 12,
axisLabelFontFamily: 'Verdana, Arial',
axisLabelPadding: 6
}, {
max: 5120,
position: "right",
axisLabel: "Disk",
axisLabelUseCanvas: true,
axisLabelFontSizePixels: 12,
axisLabelFontFamily: 'Verdana, Arial',
axisLabelPadding: 6
}
],
legend: {
noColumns: 0,
position: "nw"
},
grid: {
backgroundColor: {colors: ["#ffffff", "#EDF5FF"]}
}
};
function initData() {
for (var i = 0; i < totalPoints; i++) {
var temp = [now += updateInterval, 0];
cpu.push(temp);
}
}
function GetData() {
var data = {
domain: $("#domain").text()
};
$.ajaxSetup({cache: false});
$.ajax({
url: "/CloudLinux/getUsageData",
dataType: 'json',
success: update,
type: "POST",
headers: {'X-CSRFToken': getCookie('csrftoken')},
contentType: "application/json",
data: JSON.stringify(data), // Our valid JSON string
error: function () {
setTimeout(GetData, updateInterval);
}
});
}
var temp;
function update(_data) {
cpu.shift();
now += updateInterval;
temp = [now, _data.cpu];
cpu.push(temp);
dataset = [
{label: "CPU:" + _data.cpu + "%", data: cpu, lines: {fill: true, lineWidth: 1.2}, color: "#00FF00"}
];
$.plot($("#flot-placeholder1"), dataset, options);
setTimeout(GetData, updateInterval);
}
// Memory Usage of User
var memory = [];
var datasetMemory;
var totalPointsMemory = 100;
var updateIntervalMemory = 1000;
var nowMemory = new Date().getTime();
var optionsMemory = {
series: {
lines: {
lineWidth: 1.2
},
bars: {
align: "center",
fillColor: {colors: [{opacity: 1}, {opacity: 1}]},
barWidth: 500,
lineWidth: 1
}
},
xaxis: {
mode: "time",
tickSize: [5, "second"],
tickFormatter: function (v, axis) {
var date = new Date(v);
if (date.getSeconds() % 20 == 0) {
var hours = date.getHours() < 10 ? "0" + date.getHours() : date.getHours();
var minutes = date.getMinutes() < 10 ? "0" + date.getMinutes() : date.getMinutes();
var seconds = date.getSeconds() < 10 ? "0" + date.getSeconds() : date.getSeconds();
return hours + ":" + minutes + ":" + seconds;
} else {
return "";
}
},
axisLabel: "Time",
axisLabelUseCanvas: true,
axisLabelFontSizePixels: 12,
axisLabelFontFamily: 'Verdana, Arial',
axisLabelPadding: 10
},
yaxes: [
{
min: 0,
max: $scope.memory,
tickSize: 5,
tickFormatter: function (v, axis) {
if (v % 10 == 0) {
return v + "MB";
} else {
return "";
}
},
axisLabel: "CPU loading",
axisLabelUseCanvas: true,
axisLabelFontSizePixels: 12,
axisLabelFontFamily: 'Verdana, Arial',
axisLabelPadding: 6
}, {
max: 5120,
position: "right",
axisLabel: "Disk",
axisLabelUseCanvas: true,
axisLabelFontSizePixels: 12,
axisLabelFontFamily: 'Verdana, Arial',
axisLabelPadding: 6
}
],
legend: {
noColumns: 0,
position: "nw"
},
grid: {
backgroundColor: {colors: ["#ffffff", "#EDF5FF"]}
}
};
function initDataMemory() {
for (var i = 0; i < totalPointsMemory; i++) {
var temp = [nowMemory += updateIntervalMemory, 0];
memory.push(temp);
}
}
function GetDataMemory() {
var data = {
domain: $("#domain").text(),
type: 'memory'
};
$.ajaxSetup({cache: false});
$.ajax({
url: "/CloudLinux/getUsageData",
dataType: 'json',
headers: {'X-CSRFToken': getCookie('csrftoken')},
success: updateMemory,
type: "POST",
contentType: "application/json",
data: JSON.stringify(data), // Our valid JSON string
error: function () {
setTimeout(GetDataMemory, updateIntervalMemory);
}
});
}
var tempMemory;
function updateMemory(_data) {
memory.shift();
nowMemory += updateIntervalMemory;
tempMemory = [nowMemory, _data.memory];
memory.push(tempMemory);
datasetMemory = [
{
label: "Memory:" + _data.memory + "MB",
data: memory,
lines: {fill: true, lineWidth: 1.2},
color: "#00FF00"
}
];
$.plot($("#memoryUsage"), datasetMemory, optionsMemory);
setTimeout(GetDataMemory, updateIntervalMemory);
}
// Disk Usage
var readRate = [], writeRate = [];
var datasetDisk;
var totalPointsDisk = 100;
var updateIntervalDisk = 5000;
var now = new Date().getTime();
var optionsDisk = {
series: {
lines: {
lineWidth: 1.2
},
bars: {
align: "center",
fillColor: {colors: [{opacity: 1}, {opacity: 1}]},
barWidth: 500,
lineWidth: 1
}
},
xaxis: {
mode: "time",
tickSize: [30, "second"],
tickFormatter: function (v, axis) {
var date = new Date(v);
if (date.getSeconds() % 20 == 0) {
var hours = date.getHours() < 10 ? "0" + date.getHours() : date.getHours();
var minutes = date.getMinutes() < 10 ? "0" + date.getMinutes() : date.getMinutes();
var seconds = date.getSeconds() < 10 ? "0" + date.getSeconds() : date.getSeconds();
return hours + ":" + minutes + ":" + seconds;
} else {
return "";
}
},
axisLabel: "Time",
axisLabelUseCanvas: true,
axisLabelFontSizePixels: 12,
axisLabelFontFamily: 'Verdana, Arial',
axisLabelPadding: 10
},
yaxes: [
{
min: 0,
max: $scope.networkSpeed,
tickSize: 5,
tickFormatter: function (v, axis) {
if (v % 10 == 0) {
return v + "mb/sec";
} else {
return "";
}
},
axisLabel: "CPU loading",
axisLabelUseCanvas: true,
axisLabelFontSizePixels: 12,
axisLabelFontFamily: 'Verdana, Arial',
axisLabelPadding: 6
}, {
max: 5120,
position: "right",
axisLabel: "Disk",
axisLabelUseCanvas: true,
axisLabelFontSizePixels: 12,
axisLabelFontFamily: 'Verdana, Arial',
axisLabelPadding: 6
}
],
legend: {
noColumns: 0,
position: "nw"
},
grid: {
backgroundColor: {colors: ["#ffffff", "#EDF5FF"]}
}
};
function initDataDisk() {
for (var i = 0; i < totalPointsDisk; i++) {
var temp = [now += updateIntervalDisk, 0];
readRate.push(temp);
writeRate.push(temp);
}
}
function GetDataDisk() {
var data = {
domain: $("#domain").text(),
type: 'io'
};
$.ajaxSetup({cache: false});
$.ajax({
url: "/CloudLinux/getUsageData",
dataType: 'json',
headers: {'X-CSRFToken': getCookie('csrftoken')},
success: updateDisk,
type: "POST",
contentType: "application/json",
data: JSON.stringify(data), // Our valid JSON string
error: function () {
setTimeout(GetDataMemory, updateIntervalMemory);
}
});
}
var tempDisk;
function updateDisk(_data) {
readRate.shift();
writeRate.shift();
now += updateIntervalDisk;
tempDisk = [now, _data.readRate];
readRate.push(tempDisk);
tempDisk = [now, _data.readRate];
writeRate.push(tempDisk);
datasetDisk = [
{
label: "Read IO/s " + _data.readRate + " mb/s ",
data: readRate,
lines: {fill: true, lineWidth: 1.2},
color: "#00FF00"
},
{
label: "Write IO/s " + _data.writeRate + " mb/s ",
data: writeRate,
lines: {lineWidth: 1.2},
color: "#FF0000"
}
];
$.plot($("#diskUsage"), datasetDisk, optionsDisk);
setTimeout(GetDataDisk, updateIntervalDisk);
}
$(document).ready(function () {
// Report Memory Usage
initDataMemory();
datasetMemory = [
{label: "Memory", data: memory, lines: {fill: true, lineWidth: 1.2}, color: "#00FF00"}
];
$.plot($("#memoryUsage"), datasetMemory, optionsMemory);
setTimeout(GetDataMemory, updateIntervalMemory);
// Report CPU Usage
initData();
dataset = [
{label: "CPU", data: cpu, lines: {fill: true, lineWidth: 1.2}, color: "#00FF00"}
];
$.plot($("#flot-placeholder1"), dataset, options);
setTimeout(GetData, updateInterval);
// Report Disk Usage
initDataDisk();
datasetDisk = [
{label: "Read IO/s: ", data: readRate, lines: {fill: true, lineWidth: 1.2}, color: "#00FF00"},
{label: "Write IO/s: ", data: writeRate, color: "#0044FF", bars: {show: true}, yaxis: 2}
];
$.plot($("#diskUsage"), datasetDisk, optionsDisk);
setTimeout(GetDataDisk, updateIntervalDisk);
});
});

View File

@ -0,0 +1,146 @@
{% extends "baseTemplate/index.html" %}
{% load i18n %}
{% block title %}{% trans "Create Cloud Linux Package - CyberPanel" %}{% endblock %}
{% block content %}
{% load static %}
<div class="container">
<div id="page-title">
<h2>{% trans "Create CloudLinux Package." %}</h2>
<p>{% trans "Each CloudLinux package have one associated (owner) CyberPanel package. During website creation associated CloudLinux package will be assigned to website user." %}</p>
</div>
<div ng-controller="createCLPackage" class="panel">
<div class="panel-body">
<h3 class="content-box-header">
{% trans "Create Package" %} <img ng-hide="cyberPanelLoading" src="{% static 'images/loading.gif' %}">
</h3>
<div class="example-box-wrapper">
<form action="/" class="form-horizontal bordered-row panel-body">
<div class="form-group">
<label class="col-sm-3 control-label">{% trans "Select Package" %} </label>
<div class="col-sm-6">
<select ng-change="toggleView()" ng-model="selectedPackage" class="form-control">
{% for items in packList %}
<option>{{ items }}</option>
{% endfor %}
</select>
</div>
</div>
<!------ Modification form that appears after a click --------------->
<div ng-hide="modifyPackageForm">
<div class="form-group">
<label class="col-sm-3 control-label">{% trans "Package Name" %}</label>
<div class="col-sm-6">
<input type="text" class="form-control" ng-model="name" required>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">{% trans "SPEED" %}</label>
<div class="col-sm-6">
<input type="text" class="form-control" ng-model="SPEED" required>
</div>
<div class="current-pack ng-binding">Ex 100%</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">{% trans "VMEM" %}</label>
<div class="col-sm-6">
<input type="text" class="form-control" ng-model="VMEM" required>
</div>
<div class="current-pack ng-binding">Ex 256m or 1G</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">{% trans "PMEM" %}</label>
<div class="col-sm-6">
<input type="text" class="form-control" ng-model="PMEM" required>
</div>
<div class="current-pack ng-binding">Ex 256m or 1G</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">{% trans "IO" %}</label>
<div class="col-sm-6">
<input type="text" class="form-control" ng-model="IO" required>
</div>
<div class="current-pack ng-binding">Ex 1024</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">{% trans "IOPS" %}</label>
<div class="col-sm-6">
<input type="text" class="form-control" ng-model="IOPS" required>
</div>
<div class="current-pack ng-binding">Ex 1024</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">{% trans "EP" %}</label>
<div class="col-sm-6">
<input type="text" class="form-control" ng-model="EP" required>
</div>
<div class="current-pack ng-binding">Ex 10</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">{% trans "NPROC" %}</label>
<div class="col-sm-6">
<input type="text" class="form-control" ng-model="NPROC" required>
</div>
<div class="current-pack ng-binding">Ex 10</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">{% trans "INODES soft" %}</label>
<div class="col-sm-6">
<input type="text" class="form-control" ng-model="INODESsoft" required>
</div>
<div class="current-pack ng-binding">Ex 1024</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">{% trans "INODES hard" %}</label>
<div class="col-sm-6">
<input type="text" class="form-control" ng-model="INODEShard" required>
</div>
<div class="current-pack ng-binding">Ex 1024</div>
</div>
</div>
<!------ Modification form that appears after a click --------------->
<div ng-hide="modifyPackageForm" class="form-group">
<label class="col-sm-3 control-label"></label>
<div class="col-sm-4">
<button type="button" ng-click="createPackage()"
class="btn btn-primary btn-lg ">{% trans "Create Package" %}</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,236 @@
{% extends "baseTemplate/index.html" %}
{% load i18n %}
{% block title %}{% trans "Manage CloudLinux Packages - CyberPanel" %}{% endblock %}
{% block content %}
{% load static %}
{% get_current_language as LANGUAGE_CODE %}
<!-- Current language: {{ LANGUAGE_CODE }} -->
<div ng-controller="listCloudLinuxPackages" class="container">
<div id="page-title">
<h2 id="domainNamePage">{% trans "Manage CloudLinux Packages" %}</h2>
<p>{% trans "Manage/Delete CloudLinux Packages." %}</p>
</div>
<div class="panel">
<div class="panel-body">
<div class="example-box-wrapper">
<table cellpadding="0" cellspacing="0" border="0" class="table table-striped table-bordered"
id="datatable-example">
<thead>
<tr>
<th>Name<img ng-hide="cyberPanelLoading" src="/static/images/loading.gif"></th>
<th>SPEED</th>
<th>VMEM</th>
<th>PMEM</th>
<th>IO</th>
<th>IOPS</th>
<th>EP</th>
<th>NPROC</th>
<th>INODES soft</th>
<th>INODES hard</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="pack in packages track by $index">
<td ng-bind="pack.name"></td>
<td ng-bind="pack.SPEED"></td>
<td ng-bind="pack.VMEM"></td>
<td ng-bind="pack.PMEM"></td>
<td ng-bind="pack.IO"></td>
<td ng-bind="pack.IOPS"></td>
<td ng-bind="pack.EP"></td>
<td ng-bind="pack.NPROC"></td>
<td ng-bind="pack.inodessoft"></td>
<td ng-bind="pack.inodeshard"></td>
<td>
<a ng-click='deleteCLPackage(pack.name)'
class="btn btn-border btn-alt border-red btn-link font-red"
title=""><span>Delete</span></a>
<a ng-click="populatePackage(pack.name, pack.SPEED, pack.VMEM, pack.PMEM, pack.IO, pack.IOPS, pack.EP, pack.NPROC, pack.inodessoft, pack.inodeshard)" data-toggle="modal" data-target="#settings" ng-click='deleteCLPackage()'
class="btn btn-border btn-alt border-green btn-link font-green"
title=""><span>Edit</span></a>
<div id="settings" class="modal fade" role="dialog">
<div class="modal-dialog">
<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">&times;
</button>
<h4 class="modal-title">Edit Package
<img id="containerSettingLoading" src="/static/images/loading.gif"
style="display: none;">
</h4>
</div>
<div class="modal-body">
<form name="containerSettingsForm" action="/" class="form-horizontal">
<div ng-hide="installationDetailsForm" class="form-group">
<label class="col-sm-3 control-label">{% trans "Name" %}</label>
<div class="col-sm-6">
<input name="name" type="text" class="form-control"
ng-model="name" readonly>
</div>
</div>
<hr>
<div ng-hide="installationDetailsForm" class="form-group">
<div ng-hide="installationDetailsForm" class="form-group">
<label class="col-sm-3 control-label">{% trans "SPEED" %}</label>
<div class="col-sm-6">
<input name="SPEED" type="text" class="form-control"
ng-model="$parent.SPEED" required>
</div>
</div>
</div>
<hr>
<div ng-hide="installationDetailsForm" class="form-group">
<div ng-hide="installationDetailsForm" class="form-group">
<label class="col-sm-3 control-label">{% trans "VMEM" %}</label>
<div class="col-sm-6">
<input name="VMEM" type="text" class="form-control"
ng-model="$parent.VMEM" required>
</div>
</div>
</div>
<hr>
<div ng-hide="installationDetailsForm" class="form-group">
<div ng-hide="installationDetailsForm" class="form-group">
<label class="col-sm-3 control-label">{% trans "PMEM" %}</label>
<div class="col-sm-6">
<input name="PMEM" type="text" class="form-control"
ng-model="$parent.PMEM" required>
</div>
</div>
</div>
<hr>
<div ng-hide="installationDetailsForm" class="form-group">
<div ng-hide="installationDetailsForm" class="form-group">
<label class="col-sm-3 control-label">{% trans "IO" %}</label>
<div class="col-sm-6">
<input name="IO" type="text" class="form-control"
ng-model="$parent.IO" required>
</div>
</div>
</div>
<hr>
<div ng-hide="installationDetailsForm" class="form-group">
<div ng-hide="installationDetailsForm" class="form-group">
<label class="col-sm-3 control-label">{% trans "IOPS" %}</label>
<div class="col-sm-6">
<input name="IOPS" type="text" class="form-control"
ng-model="$parent.IOPS" required>
</div>
</div>
</div>
<hr>
<div ng-hide="installationDetailsForm" class="form-group">
<div ng-hide="installationDetailsForm" class="form-group">
<label class="col-sm-3 control-label">{% trans "EP" %}</label>
<div class="col-sm-6">
<input name="EP" type="text" class="form-control"
ng-model="$parent.EP" required>
</div>
</div>
</div>
<hr>
<div ng-hide="installationDetailsForm" class="form-group">
<div ng-hide="installationDetailsForm" class="form-group">
<label class="col-sm-3 control-label">{% trans "NPROC" %}</label>
<div class="col-sm-6">
<input name="NPROC" type="text" class="form-control"
ng-model="$parent.NPROC" required>
</div>
</div>
</div>
<hr>
<div ng-hide="installationDetailsForm" class="form-group">
<div ng-hide="installationDetailsForm" class="form-group">
<label class="col-sm-3 control-label">{% trans "INODES soft" %}</label>
<div class="col-sm-6">
<input name="inodessoft" type="text" class="form-control"
ng-model="$parent.inodessoft" required>
</div>
</div>
</div>
<hr>
<div ng-hide="installationDetailsForm" class="form-group">
<div ng-hide="installationDetailsForm" class="form-group">
<label class="col-sm-3 control-label">{% trans "INODES hard" %}</label>
<div class="col-sm-6">
<input name="inodeshard" type="text" class="form-control"
ng-model="$parent.inodeshard" required>
</div>
</div>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" ng-disabled="savingSettings"
class="btn btn-primary"
ng-click="saveSettings()" data-dismiss="modal">Save
</button>
<button type="button" ng-disabled="savingSettings"
class="btn btn-default" data-dismiss="modal">
Close
</button>
</div>
</div>
</div>
</div>
</td>
</tr>
</tbody>
</table>
<div id="listFail" class="alert alert-danger">
<p>{% trans "Cannot list websites. Error message:" %} {$ errorMessage $}</p>
</div>
<div class="row">
<div class="col-sm-4 col-sm-offset-8">
<nav aria-label="Page navigation">
<ul class="pagination">
<li ng-repeat="page in pagination" ng-click="getFurtherWebsitesFromDB($index+1)"
id="webPages"><a
href="">{$ $index + 1 $}</a></li>
</ul>
</nav>
</div>
</div>
</div>
</div>
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,117 @@
{% extends "baseTemplate/index.html" %}
{% load i18n %}
{% block title %}{% trans "CageFS - CyberPanel" %}{% endblock %}
{% block content %}
{% load static %}
{% get_current_language as LANGUAGE_CODE %}
<!-- Current language: {{ LANGUAGE_CODE }} -->
<div ng-controller="listWebsitesCage" class="container">
<div id="page-title">
<h2 id="domainNamePage">{% trans "List Websites" %}</h2>
<p>{% trans "Enable/Disable and view CageFS status for websites." %}</p>
</div>
<div class="panel">
<div class="panel-body">
<div style="padding-bottom: 0px; padding-top: 15px;" class="form-group">
<label class="col-sm-3 control-label"></label>
<div class="col-sm-6">
<div class="example-box-wrapper">
<div class="content-box remove-border clearfix text-center">
<a class="btn btn-primary" href="#" title="">
<span>{% trans "Default: " %}
<b>{$ default $}</b></span>
</a>
<a href="#" ng-click="enableOrDisable(0, 0, 0, 1)"
class="btn btn-border btn-alt border-green btn-link font-green"
title=""><span>Toggle Default</span></a>
<a href="#" ng-click="enableOrDisable(0, 1, 1, 0)" class="btn btn-success" title="Enable All">
<i class="fa fa-play btn-icon"></i>
</a>
<a href="#" ng-click="enableOrDisable(0, 1, 0, 0)" class="btn btn-warning" title="Disable All">
<i class="fa fa-pause btn-icon"></i>
</a>
<a href="#" ng-click="refreshStatus()" class="btn btn-info" title="Refresh Status">
<i class="fa fa-refresh btn-icon"></i>
</a>
</div>
</div>
</div>
</div>
<div class="example-box-wrapper">
<table cellpadding="0" cellspacing="0" border="0" class="table table-striped table-bordered"
id="datatable-example">
<thead>
<tr>
<th>Domain <img ng-hide="cyberPanelLoading" src="/static/images/loading.gif"></th>
<th>User</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="web in WebSitesList track by $index">
<td ng-bind="web.domain"></td>
<td ng-bind="web.externalApp"></td>
<td>
<a ng-click="enableOrDisable(web.domain, 0, 0, 0)" ng-hide="web.status==0"
class="btn btn-border btn-alt border-red btn-link font-red"
title=""><span>Disable</span></a>
<a ng-click="enableOrDisable(web.domain, 0, 1, 0)" ng-hide="web.status==1"
class="btn btn-border btn-alt border-green btn-link font-green"
title=""><span>Enable</span></a>
</td>
</tr>
</tbody>
</table>
<div id="listFail" class="alert alert-danger">
<p>{% trans "Cannot list websites. Error message:" %} {$ errorMessage $}</p>
</div>
<div class="row">
<div class="col-sm-4 col-sm-offset-8">
<nav aria-label="Page navigation">
<ul class="pagination">
<li ng-repeat="page in pagination" ng-click="getFurtherWebsitesFromDB($index+1)"
id="webPages"><a
href="">{$ $index + 1 $}</a></li>
</ul>
</nav>
</div>
</div>
</div>
</div>
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,87 @@
{% extends "baseTemplate/index.html" %}
{% load i18n %}
{% block title %}{% trans "Monitor Usage - CyberPanel" %}{% endblock %}
{% block content %}
{% load static %}
{% get_current_language as LANGUAGE_CODE %}
<!-- Current language: {{ LANGUAGE_CODE }} -->
<div class="container">
<div id="page-title">
<h2 id="domainNamePage">{% trans "List Websites" %}</h2>
<p>{% trans "Monitor usage of your websites." %}</p>
</div>
<div class="panel">
<div class="panel-body">
<h3 class="title-hero">
{% trans "Websites" %}
</h3>
<div ng-controller="listWebsites" class="example-box-wrapper">
<table cellpadding="0" cellspacing="0" border="0" class="table table-striped table-bordered"
id="datatable-example">
<thead>
<tr>
<th>Domain</th>
<th>Launch</th>
<th>IP Address</th>
<th>Package</th>
<th>Owner</th>
<th>State</th>
<th>Email</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="web in WebSitesList track by $index">
<td ng-bind="web.domain"></td>
<td><a href="/CloudLinux/manage/{$ web.domain $}"><img width="30px" height="30"
class="center-block"
src="{% static 'baseTemplate/assets/image-resources/webPanel.png' %}"></a>
</td>
<td ng-bind="web.ipAddress"></td>
<td ng-bind="web.package"></td>
<td ng-bind="web.admin"></td>
<td ng-bind="web.state"></td>
<td ng-bind="web.adminEmail"></td>
</tr>
</tbody>
</table>
<div id="listFail" class="alert alert-danger">
<p>{% trans "Cannot list websites. Error message:" %} {$ errorMessage $}</p>
</div>
<div class="row">
<div class="col-sm-4 col-sm-offset-8">
<nav aria-label="Page navigation">
<ul class="pagination">
<li ng-repeat="page in pagination" ng-click="getFurtherWebsitesFromDB($index+1)" id="webPages"><a
href="">{$ $index + 1 $}</a></li>
</ul>
</nav>
</div>
</div>
</div>
</div>
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,67 @@
{% extends "baseTemplate/index.html" %}
{% load i18n %}
{% block title %}{% trans "Not available - CyberPanel" %}{% endblock %}
{% block content %}
{% load static %}
{% get_current_language as LANGUAGE_CODE %}
<!-- Current language: {{ LANGUAGE_CODE }} -->
<div class="container">
<div id="page-title">
<h2>{% trans "Not available" %}</h2>
<p>{% trans "Either CageFS is not installed or you are not on CloudLinux OS." %}</p>
</div>
{% if not CL %}
<div class="row">
<div class="col-sm-12">
<div class="alert alert-danger">
<p>{% trans "CageFS is only available with CloudLinux OS. " %} <a target="_blank"
href="https://go.cyberpanel.net/CLConvert">Click
Here</a> {% trans " for conversion details." %}</p>
</div>
</div>
</div>
{% else %}
<div ng-controller="installCageFS" class="panel">
<div class="panel-body">
<h3 class="title-hero">
{% trans "Install Packages" %} <img ng-hide="installDockerStatus"
src="{% static 'images/loading.gif' %}">
</h3>
<div class="example-box-wrapper">
<p>{% trans "CageFS is not installed on this server. Please proceed to installation." %}</p>
<!------ LSWS Switch box ----------------->
<div style="margin-top: 2%" ng-hide="installBoxGen" class="col-md-12">
<form action="/" id="" class="form-horizontal bordered-row">
<div class="form-group">
<div style="margin-top: 2%;" class="col-sm-12">
<textarea ng-model="requestData" rows="15"
class="form-control">{{ requestData }}</textarea>
</div>
</div>
</form>
</div>
<!----- LSWS Switch box ----------------->
<br>
<button ng-hide="dockerInstallBTN" class="btn btn-primary" ng-click="submitCageFSInstall()">Install Now</button>
</div>
</div>
</div>
{% endif %}
</div>
{% endblock %}

View File

@ -0,0 +1,52 @@
{% extends "baseTemplate/index.html" %}
{% load i18n %}
{% block title %}{{ domain }}{% trans " usage - CyberPanel" %}{% endblock %}
{% block content %}
{% load static %}
{% get_current_language as LANGUAGE_CODE %}
<!-- Current language: {{ LANGUAGE_CODE }} -->
<div ng-controller="websiteContainerLimitCL" class="container">
<div id="page-title">
<h2 id="domainNamePage">{% trans "Usage" %}</h2>
<p>{% trans "View CPU, Memory and Disk usage for " %} <span id="domain">{{ domain }}</span></p>
</div>
<div class="panel">
<div class="panel-body">
<h2 class="title-hero">
{% trans "CPU Usage of" %} {{ domain }}
</h2>
<div class="example-box-wrapper">
<div id="flot-placeholder1" style="width:auto;height:300px"></div>
</div>
</div>
<div class="panel-body">
<h2 class="title-hero">
{% trans "Memory Usage of" %} {{ domain }}
</h2>
<div class="example-box-wrapper">
<div id="memoryUsage" style="width:auto;height:300px"></div>
</div>
</div>
<div class="panel-body">
<h2 class="title-hero">
{% trans "Disk Usage of" %} {{ domain }}
</h2>
<div class="example-box-wrapper">
<div id="diskUsage" style="width:auto;height:300px"></div>
</div>
</div>
</div>
</div>
{% endblock %}

6
CLManager/tests.py Normal file
View File

@ -0,0 +1,6 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.test import TestCase
# Create your tests here.

18
CLManager/urls.py Normal file
View File

@ -0,0 +1,18 @@
from django.conf.urls import url
import views
urlpatterns = [
url(r'^CageFS$', views.CageFS, name='CageFS'),
url(r'^submitCageFSInstall$', views.submitCageFSInstall, name='submitCageFSInstall'),
url(r'^submitWebsiteListing$', views.getFurtherAccounts, name='submitWebsiteListing'),
url(r'^enableOrDisable$', views.enableOrDisable, name='enableOrDisable'),
url(r'^CreatePackage$', views.CreatePackage, name='CreatePackageCL'),
url(r'^submitCreatePackage$', views.submitCreatePackage, name='submitCreatePackageCL'),
url(r'^listPackages$', views.listPackages, name='listPackagesCL'),
url(r'^fetchPackages$', views.fetchPackages, name='fetchPackagesCL'),
url(r'^deleteCLPackage$', views.deleteCLPackage, name='deleteCLPackage'),
url(r'^saveSettings$', views.saveSettings, name='saveSettings'),
url(r'^monitorUsage$', views.monitorUsage, name='monitorUsage'),
url(r'^manage/(?P<domain>(.*))$', views.websiteContainerLimit, name='websiteContainerLimitCL'),
url(r'^getUsageData$', views.getUsageData, name='getUsageData'),
]

358
CLManager/views.py Normal file
View File

@ -0,0 +1,358 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.shortcuts import redirect, HttpResponse
from loginSystem.views import loadLoginPage
from plogical.acl import ACLManager
from CLManagerMain import CLManagerMain
import json
from websiteFunctions.models import Websites
from plogical.processUtilities import ProcessUtilities
import os
from packages.models import Package
from .models import CLPackages
import subprocess
import multiprocessing
import pwd
from plogical.CyberCPLogFileWriter import CyberCPLogFileWriter as logging
# Create your views here.
def CageFS(request):
try:
templateName = 'CLManager/listWebsites.html'
c = CLManagerMain(request, templateName)
return c.renderC()
except KeyError:
return redirect(loadLoginPage)
def submitCageFSInstall(request):
try:
userID = request.session['userID']
currentACL = ACLManager.loadedACL(userID)
if currentACL['admin'] == 1:
pass
else:
return ACLManager.loadErrorJson()
c = CLManagerMain(request, None, 'submitCageFSInstall')
c.start()
data_ret = {'status': 1, 'error_message': 'None'}
json_data = json.dumps(data_ret)
return HttpResponse(json_data)
except BaseException, msg:
data_ret = {'status': 0, 'error_message': str(msg)}
json_data = json.dumps(data_ret)
return HttpResponse(json_data)
def getFurtherAccounts(request):
try:
userID = request.session['userID']
wm = CLManagerMain()
return wm.getFurtherAccounts(userID, json.loads(request.body))
except KeyError:
return redirect(loadLoginPage)
def enableOrDisable(request):
try:
userID = request.session['userID']
currentACL = ACLManager.loadedACL(userID)
if currentACL['admin'] == 1:
pass
else:
return ACLManager.loadErrorJson()
data = json.loads(request.body)
if data['toggle'] == 1:
cageFSPath = '/home/cyberpanel/cagefs'
if os.path.exists(cageFSPath):
os.remove(cageFSPath)
else:
writeToFile = open(cageFSPath, 'w')
writeToFile.writelines('enable')
writeToFile.close()
data_ret = {'status': 1, 'error_message': 'None', 'success': 'Default status successfully changed changed.'}
json_data = json.dumps(data_ret)
return HttpResponse(json_data)
if data['all'] == 0:
if data['mode'] == 1:
website = Websites.objects.get(domain=data['domain'])
command = '/usr/sbin/cagefsctl --enable %s' % (website.externalApp)
else:
website = Websites.objects.get(domain=data['domain'])
command = '/usr/sbin/cagefsctl --disable %s' % (website.externalApp)
ProcessUtilities.executioner(command)
data_ret = {'status': 1, 'error_message': 'None', 'success': 'Changes successfully applied.'}
json_data = json.dumps(data_ret)
return HttpResponse(json_data)
else:
c = CLManagerMain(request, None, 'enableOrDisable', data)
c.start()
data_ret = {'status': 1, 'error_message': 'None', 'success': 'Job started in background, refresh in few seconds to see the status.'}
json_data = json.dumps(data_ret)
return HttpResponse(json_data)
except BaseException, msg:
data_ret = {'status': 0, 'error_message': str(msg)}
json_data = json.dumps(data_ret)
return HttpResponse(json_data)
def CreatePackage(request):
try:
userID = request.session['userID']
currentACL = ACLManager.loadedACL(userID)
templateName = 'CLManager/createPackage.html'
packageList = ACLManager.loadPackages(userID, currentACL)
data = {}
data['packList'] = packageList
c = CLManagerMain(request, templateName, None, data)
return c.renderC()
except KeyError:
return redirect(loadLoginPage)
def submitCreatePackage(request):
try:
userID = request.session['userID']
currentACL = ACLManager.loadedACL(userID)
if currentACL['admin'] == 1:
pass
else:
return ACLManager.loadErrorJson()
data = json.loads(request.body)
selectedPackage = data['selectedPackage']
package = Package.objects.get(packageName=selectedPackage)
if package.clpackages_set.all().count() == 1:
data_ret = {'status': 0, 'error_message': 'This package already have one associated CloudLinux Package.'}
json_data = json.dumps(data_ret)
return HttpResponse(json_data)
name = data['name']
SPEED = data['SPEED']
VMEM = data['VMEM']
PMEM = data['PMEM']
IO = data['IO']
IOPS = data['IOPS']
EP = data['EP']
NPROC = data['NPROC']
INODESsoft = data['INODESsoft']
INODEShard = data['INODEShard']
clPackage = CLPackages(name=name, owner=package, speed=SPEED, vmem=VMEM, pmem=PMEM, io=IO, iops=IOPS, ep=EP, nproc=NPROC, inodessoft=INODESsoft, inodeshard=INODEShard)
clPackage.save()
command = 'sudo lvectl package-set %s --speed=%s --pmem=%s --io=%s --nproc=%s --iops=%s --vmem=%s --ep=%s' % (name, SPEED, PMEM, IO, NPROC, IOPS, VMEM, EP)
ProcessUtilities.executioner(command)
command = 'sudo lvectl apply all'
ProcessUtilities.popenExecutioner(command)
data_ret = {'status': 1}
json_data = json.dumps(data_ret)
return HttpResponse(json_data)
except BaseException, msg:
data_ret = {'status': 0, 'error_message': str(msg)}
json_data = json.dumps(data_ret)
return HttpResponse(json_data)
def listPackages(request):
try:
templateName = 'CLManager/listPackages.html'
c = CLManagerMain(request, templateName)
return c.renderC()
except KeyError:
return redirect(loadLoginPage)
def fetchPackages(request):
try:
userID = request.session['userID']
wm = CLManagerMain()
return wm.fetchPackages(ACLManager.loadedACL(userID))
except KeyError:
return redirect(loadLoginPage)
def deleteCLPackage(request):
try:
userID = request.session['userID']
currentACL = ACLManager.loadedACL(userID)
if currentACL['admin'] == 1:
pass
else:
return ACLManager.loadErrorJson()
data = json.loads(request.body)
name = data['name']
clPackage = CLPackages.objects.get(name=name)
clPackage.delete()
data_ret = {'status': 1}
json_data = json.dumps(data_ret)
return HttpResponse(json_data)
except BaseException, msg:
data_ret = {'status': 0, 'error_message': str(msg)}
json_data = json.dumps(data_ret)
return HttpResponse(json_data)
def saveSettings(request):
try:
userID = request.session['userID']
currentACL = ACLManager.loadedACL(userID)
if currentACL['admin'] == 1:
pass
else:
return ACLManager.loadErrorJson()
data = json.loads(request.body)
name = data['name']
SPEED = data['SPEED']
VMEM = data['VMEM']
PMEM = data['PMEM']
IO = data['IO']
IOPS = data['IOPS']
EP = data['EP']
NPROC = data['NPROC']
INODESsoft = data['INODESsoft']
INODEShard = data['INODEShard']
clPackage = CLPackages.objects.get(name=name)
clPackage.speed = SPEED
clPackage.vmem = VMEM
clPackage.pmem = PMEM
clPackage.io = IO
clPackage.iops = IOPS
clPackage.ep = EP
clPackage.nproc = NPROC
clPackage.inodessoft = INODESsoft
clPackage.inodeshard = INODEShard
clPackage.save()
command = 'sudo lvectl package-set %s --speed=%s --pmem=%s --io=%s --nproc=%s --iops=%s --vmem=%s --ep=%s' % (
name, SPEED, PMEM, IO, NPROC, IOPS, VMEM, EP)
ProcessUtilities.executioner(command)
command = 'sudo lvectl apply all'
ProcessUtilities.popenExecutioner(command)
data_ret = {'status': 1}
json_data = json.dumps(data_ret)
return HttpResponse(json_data)
except BaseException, msg:
data_ret = {'status': 0, 'error_message': str(msg)}
json_data = json.dumps(data_ret)
return HttpResponse(json_data)
def monitorUsage(request):
try:
templateName = 'CLManager/monitorUsage.html'
c = CLManagerMain(request, templateName)
return c.renderC()
except KeyError:
return redirect(loadLoginPage)
def websiteContainerLimit(request, domain):
try:
templateName = 'CLManager/websiteContainerLimit.html'
data = {}
data['domain'] = domain
c = CLManagerMain(request, templateName, None, data)
return c.renderC()
except KeyError:
return redirect(loadLoginPage)
def getUsageData(request):
try:
userID = request.session['userID']
currentACL = ACLManager.loadedACL(userID)
if currentACL['admin'] == 1:
pass
else:
return ACLManager.loadErrorJson()
data = json.loads(request.body)
domain = data['domain']
website = Websites.objects.get(domain=domain)
uid = pwd.getpwnam(website.externalApp).pw_uid
try:
type = data['type']
finalData = {}
finalData['status'] = 1
try:
if type == 'memory':
command = 'sudo lveps -o id:10,mem:10'
output = ProcessUtilities.outputExecutioner(command).splitlines()
for items in output:
if items.find(website.externalApp) > -1:
finalData['memory'] = int(items.split(' ')[-1])
break
elif type == 'io':
finalData['readRate'] = 0
finalData['writeRate'] = 0
command = 'sudo lveps -o id:10,iops:10'
output = ProcessUtilities.outputExecutioner(command).splitlines()
for items in output:
if items.find(website.externalApp) > -1:
finalData['readRate'] = int(items.split(' ')[-1])
break
except:
finalData['memory'] = '0'
finalData['readRate'] = 0
finalData['writeRate'] = 0
except:
finalData = {}
finalData['status'] = 1
command = 'sudo lveps -o id:10,cpu:10 -d'
output = ProcessUtilities.outputExecutioner(command).splitlines()
for items in output:
if items.find(website.externalApp) > -1:
finalData['cpu'] = int(items.split(' ')[-1].rstrip('%'))
break
final_json = json.dumps(finalData)
return HttpResponse(final_json)
except BaseException, msg:
data_ret = {'status': 0, 'error_message': str(msg), 'cpu': 0, 'memory':0}
json_data = json.dumps(data_ret)
return HttpResponse(json_data)

View File

@ -1,6 +1,6 @@
from django.conf import settings
from django.shortcuts import HttpResponse
from plogical.CyberCPLogFileWriter import CyberCPLogFileWriter as logging
import json
from django.shortcuts import HttpResponse
class secMiddleware:
@ -8,8 +8,80 @@ class secMiddleware:
self.get_response = get_response
def __call__(self, request):
try:
uID = request.session['userID']
ipAddr = request.META.get('REMOTE_ADDR')
if ipAddr.find('.') > -1:
if request.session['ipAddr'] == ipAddr:
pass
else:
del request.session['userID']
del request.session['ipAddr']
logging.writeToFile(request.META.get('REMOTE_ADDR'))
final_dic = {'error_message': "Session reuse detected, IPAddress logged.",
"errorMessage": "Session reuse detected, IPAddress logged."}
final_json = json.dumps(final_dic)
return HttpResponse(final_json)
else:
ipAddr = request.META.get('REMOTE_ADDR').split(':')[:3]
if request.session['ipAddr'] == ipAddr:
pass
else:
del request.session['userID']
del request.session['ipAddr']
logging.writeToFile(request.META.get('REMOTE_ADDR'))
final_dic = {'error_message': "Session reuse detected, IPAddress logged.",
"errorMessage": "Session reuse detected, IPAddress logged."}
final_json = json.dumps(final_dic)
return HttpResponse(final_json)
except:
pass
if request.method == 'POST':
if request.body.find(';') > -1 or request.body.find('&&') > -1 or request.body.find('|') > -1 or request.body.find('...') > -1:
logging.writeToFile('Bad Input on.')
try:
#logging.writeToFile(request.body)
data = json.loads(request.body)
for key, value in data.iteritems():
if request.path.find('gitNotify') > -1:
break
# if request.path.find('users') > -1 or request.path.find('firewall') > -1 or request.path.find('servicesAction') > -1 or request.path.find('sslForHostName') > -1:
# 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 type(value) == str or type(value) == unicode:
pass
else:
continue
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':
continue
if value.find(';') > -1 or value.find('&&') > -1 or value.find('|') > -1 or value.find('...') > -1 \
or value.find("`") > -1 or value.find("$") > -1 or value.find("(") > -1 or value.find(")") > -1 \
or value.find("'") > -1 or value.find("[") > -1 or value.find("]") > -1 or value.find("{") > -1 or value.find("}") > -1\
or value.find(":") > -1 or value.find("<") > -1 or value.find(">") > -1:
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 key.find(';') > -1 or key.find('&&') > -1 or key.find('|') > -1 or key.find('...') > -1 \
or key.find("`") > -1 or key.find("$") > -1 or key.find("(") > -1 or key.find(")") > -1 \
or key.find("'") > -1 or key.find("[") > -1 or key.find("]") > -1 or key.find("{") > -1 or key.find("}") > -1\
or key.find(":") > -1 or key.find("<") > -1 or key.find(">") > -1:
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)
except BaseException, msg:
logging.writeToFile(str(msg))
response = self.get_response(request)
return response
response = self.get_response(request)
return response
return response

View File

@ -24,13 +24,10 @@ BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
SECRET_KEY = 'xr%j*p!*$0d%(-(e%@-*hyoz4$f%y77coq0u)6pwmjg4)q&19f'
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = False
DEBUG = True
ALLOWED_HOSTS = ['*']
# Application definition
INSTALLED_APPS = [
@ -58,7 +55,17 @@ INSTALLED_APPS = [
'manageSSL',
'api',
'filemanager',
'emailPremium'
'manageServices',
'pluginHolder',
'emailPremium',
'emailMarketing',
'cloudAPI',
'highAvailability',
's3Backups',
'dockerManager',
'containerization',
'CLManager',
'IncBackups'
]
MIDDLEWARE = [
@ -66,7 +73,7 @@ MIDDLEWARE = [
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.locale.LocaleMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
@ -106,7 +113,7 @@ DATABASES = {
'USER': 'cyberpanel',
'PASSWORD': 'Bz9gF7Hr7X4RtD',
'HOST': '127.0.0.1',
'PORT':'3307'
'PORT':'3306'
},
'rootdb': {
'ENGINE': 'django.db.backends.mysql',
@ -153,7 +160,6 @@ USE_L10N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.11/howto/static-files/
@ -176,4 +182,11 @@ LANGUAGES = (
('ru', _('Russian')),
('tr', _('Turkish')),
('es', _('Spanish')),
('fr', _('French')),
('pl', _('Polish')),
('vi', _('Vietnamese')),
('it', _('Italian')),
)
MEDIA_URL = '/home/cyberpanel/media/'
MEDIA_ROOT = MEDIA_URL

View File

@ -36,4 +36,12 @@ urlpatterns = [
url(r'^api/',include('api.urls')),
url(r'^filemanager/',include('filemanager.urls')),
url(r'^emailPremium/',include('emailPremium.urls')),
url(r'^manageservices/',include('manageServices.urls')),
url(r'^plugins/',include('pluginHolder.urls')),
url(r'^emailMarketing/', include('emailMarketing.urls')),
url(r'^cloudAPI/', include('cloudAPI.urls')),
url(r'^docker/', include('dockerManager.urls')),
url(r'^container/', include('containerization.urls')),
url(r'^CloudLinux/', include('CLManager.urls')),
url(r'^IncrementalBackups/', include('IncBackups.urls')),
]

375
IncBackups/IncBackups.py Normal file
View File

@ -0,0 +1,375 @@
#!/usr/local/CyberCP/bin/python2
import os,sys
sys.path.append('/usr/local/CyberCP')
import django
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "CyberCP.settings")
django.setup()
import threading as multi
from plogical.processUtilities import ProcessUtilities
import time
from .models import IncJob, JobSnapshots
from websiteFunctions.models import Websites
import plogical.randomPassword as randomPassword
from plogical.CyberCPLogFileWriter import CyberCPLogFileWriter as logging
from xml.etree.ElementTree import Element, SubElement
from xml.etree import ElementTree
from xml.dom import minidom
from backup.models import DBUsers
import plogical.mysqlUtilities as mysqlUtilities
from plogical.backupUtilities import backupUtilities
from plogical.dnsUtilities import DNS
from mailServer.models import Domains as eDomains
from random import randint
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
def run(self):
if self.function == 'createBackup':
self.createBackup()
def prepareBackupMeta(self):
try:
######### Generating meta
## XML Generation
metaFileXML = Element('metaFile')
child = SubElement(metaFileXML, 'masterDomain')
child.text = self.website.domain
child = SubElement(metaFileXML, 'phpSelection')
child.text = self.website.phpSelection
child = SubElement(metaFileXML, 'externalApp')
child.text = self.website.externalApp
childDomains = self.website.childdomains_set.all()
databases = self.website.databases_set.all()
## Child domains XML
childDomainsXML = Element('ChildDomains')
for items in childDomains:
childDomainXML = Element('domain')
child = SubElement(childDomainXML, 'domain')
child.text = items.domain
child = SubElement(childDomainXML, 'phpSelection')
child.text = items.phpSelection
child = SubElement(childDomainXML, 'path')
child.text = items.path
childDomainsXML.append(childDomainXML)
metaFileXML.append(childDomainsXML)
## Databases XML
databasesXML = Element('Databases')
for items in databases:
try:
dbuser = DBUsers.objects.get(user=items.dbUser)
userToTry = items.dbUser
except:
dbusers = DBUsers.objects.all().filter(user=items.dbUser)
userToTry = items.dbUser
for it in dbusers:
dbuser = it
break
userToTry = mysqlUtilities.mysqlUtilities.fetchuser(items.dbUser)
try:
dbuser = DBUsers.objects.get(user=userToTry)
except:
dbusers = DBUsers.objects.all().filter(user=userToTry)
for it in dbusers:
dbuser = it
break
databaseXML = Element('database')
child = SubElement(databaseXML, 'dbName')
child.text = items.dbName
child = SubElement(databaseXML, 'dbUser')
child.text = userToTry
child = SubElement(databaseXML, 'password')
child.text = dbuser.password
databasesXML.append(databaseXML)
metaFileXML.append(databasesXML)
## Get Aliases
aliasesXML = Element('Aliases')
aliases = backupUtilities.getAliases(self.website.domain)
for items in aliases:
child = SubElement(aliasesXML, 'alias')
child.text = items
metaFileXML.append(aliasesXML)
## Finish Alias
## DNS Records XML
try:
dnsRecordsXML = Element("dnsrecords")
dnsRecords = DNS.getDNSRecords(self.website.domain)
for items in dnsRecords:
dnsRecordXML = Element('dnsrecord')
child = SubElement(dnsRecordXML, 'type')
child.text = items.type
child = SubElement(dnsRecordXML, 'name')
child.text = items.name
child = SubElement(dnsRecordXML, 'content')
child.text = items.content
child = SubElement(dnsRecordXML, 'priority')
child.text = str(items.prio)
dnsRecordsXML.append(dnsRecordXML)
metaFileXML.append(dnsRecordsXML)
except BaseException, msg:
logging.statusWriter(self.statusPath, '%s. [158:prepMeta]' % (str(msg)), 1)
## Email accounts XML
try:
emailRecordsXML = Element('emails')
eDomain = eDomains.objects.get(domain=self.website.domain)
emailAccounts = eDomain.eusers_set.all()
for items in emailAccounts:
emailRecordXML = Element('emailAccount')
child = SubElement(emailRecordXML, 'email')
child.text = items.email
child = SubElement(emailRecordXML, 'password')
child.text = items.password
emailRecordsXML.append(emailRecordXML)
metaFileXML.append(emailRecordsXML)
except BaseException, msg:
logging.writeToFile(self.statusPath, '%s. [warning:179:prepMeta]' % (str(msg)), 1)
## Email meta generated!
def prettify(elem):
"""Return a pretty-printed XML string for the Element.
"""
rough_string = ElementTree.tostring(elem, 'utf-8')
reparsed = minidom.parseString(rough_string)
return reparsed.toprettyxml(indent=" ")
## /home/example.com/backup/backup-example.com-02.13.2018_10-24-52/meta.xml -- metaPath
metaPath = '/home/cyberpanel/%s' % (str(randint(1000, 9999)))
xmlpretty = prettify(metaFileXML).encode('ascii', 'ignore')
metaFile = open(metaPath, 'w')
metaFile.write(xmlpretty)
metaFile.close()
os.chmod(metaPath, 0640)
## meta generated
logging.statusWriter(self.statusPath, 'Meta data is ready..', 1)
metaPathNew = '/home/%s/meta.xml' % (self.website.domain)
command = 'mv %s %s' % (metaPath, metaPathNew)
ProcessUtilities.executioner(command)
command = 'chown %s:%s %s' % (self.website.externalApp, self.website.externalApp, metaPathNew)
ProcessUtilities.executioner(command)
return 1
except BaseException, msg:
logging.statusWriter(self.statusPath, "%s [207][5009]" % (str(msg)), 1)
return 0
def backupData(self):
try:
logging.statusWriter(self.statusPath, 'Backing up data..', 1)
if self.backupDestinations == 'local':
backupPath = '/home/%s' % (self.website.domain)
command = 'restic -r %s backup %s --password-file %s --exclude %s' % (self.repoPath, backupPath, self.passwordFile, self.repoPath)
snapShotid = ProcessUtilities.outputExecutioner(command).split(' ')[-2]
newSnapshot = JobSnapshots(job=self.jobid, type='data:%s' % (backupPath), snapshotid=snapShotid, destination=self.backupDestinations)
newSnapshot.save()
elif self.backupDestinations[:4] == 'sftp':
remotePath = '/home/backup/%s' % (self.website.domain)
backupPath = '/home/%s' % (self.website.domain)
command = 'export PATH=${PATH}:/usr/bin && restic -r %s:%s backup %s --password-file %s --exclude %s' % (self.backupDestinations, remotePath, backupPath, self.passwordFile, self.repoPath)
snapShotid = ProcessUtilities.outputExecutioner(command).split(' ')[-2]
newSnapshot = JobSnapshots(job=self.jobid, type='data:%s' % (remotePath), snapshotid=snapShotid,
destination=self.backupDestinations)
newSnapshot.save()
logging.statusWriter(self.statusPath, 'Data for %s backed to %s.' % (self.website.domain, self.backupDestinations), 1)
return 1
except BaseException, msg:
logging.statusWriter(self.statusPath,'%s. [IncJobs.backupData.223][5009]' % str(msg), 1)
return 0
def backupDatabases(self):
try:
logging.statusWriter(self.statusPath, 'Backing up databases..', 1)
databases = self.website.databases_set.all()
for items in databases:
if mysqlUtilities.mysqlUtilities.createDatabaseBackup(items.dbName, '/home/cyberpanel') == 0:
return 0
dbPath = '/home/cyberpanel/%s.sql' % (items.dbName)
if self.backupDestinations == 'local':
command = 'restic -r %s backup %s --password-file %s' % (self.repoPath, dbPath, self.passwordFile)
snapShotid = ProcessUtilities.outputExecutioner(command).split(' ')[-2]
newSnapshot = JobSnapshots(job=self.jobid, type='database:%s' % (items.dbName), snapshotid=snapShotid, destination=self.backupDestinations)
newSnapshot.save()
elif self.backupDestinations[:4] == 'sftp':
remotePath = '/home/backup/%s' % (self.website.domain)
command = 'export PATH=${PATH}:/usr/bin && restic -r %s:%s backup %s --password-file %s --exclude %s' % (
self.backupDestinations, remotePath, dbPath, self.passwordFile, self.repoPath)
snapShotid = ProcessUtilities.outputExecutioner(command).split(' ')[-2]
newSnapshot = JobSnapshots(job=self.jobid, type='database:%s' % (items.dbName), snapshotid=snapShotid,
destination=self.backupDestinations)
newSnapshot.save()
return 1
except BaseException, msg:
logging.statusWriter(self.statusPath,'%s. [IncJobs.backupDatabases.269][5009]' % str(msg), 1)
return 0
def emailBackup(self):
try:
logging.statusWriter(self.statusPath, 'Backing up emails..', 1)
backupPath = '/home/vmail/%s' % (self.website.domain)
if os.path.exists(backupPath):
if self.backupDestinations == 'local':
logging.statusWriter(self.statusPath, 'hello world', 1)
command = 'restic -r %s backup %s --password-file %s' % (
self.repoPath, backupPath, self.passwordFile)
snapShotid = ProcessUtilities.outputExecutioner(command).split(' ')[-2]
newSnapshot = JobSnapshots(job=self.jobid, type='email:%s' % (backupPath), snapshotid=snapShotid,
destination=self.backupDestinations)
newSnapshot.save()
logging.statusWriter(self.statusPath, 'hello world 2', 1)
elif self.backupDestinations[:4] == 'sftp':
remotePath = '/home/backup/%s' % (self.website.domain)
command = 'export PATH=${PATH}:/usr/bin && restic -r %s:%s backup %s --password-file %s --exclude %s' % (
self.backupDestinations, remotePath, backupPath, self.passwordFile, self.repoPath)
snapShotid = ProcessUtilities.outputExecutioner(command).split(' ')[-2]
newSnapshot = JobSnapshots(job=self.jobid, type='email:%s' % (backupPath), snapshotid=snapShotid,
destination=self.backupDestinations)
newSnapshot.save()
logging.statusWriter(self.statusPath, 'Emails for %s backed to %s.' % (self.website.domain, self.backupDestinations), 1)
return 1
except BaseException, msg:
logging.statusWriter(self.statusPath,'%s. [IncJobs.backupDatabases.269][5009]' % str(msg), 1)
return 0
def initiateRepo(self):
try:
logging.statusWriter(self.statusPath, 'Will first initiate backup repo..', 1)
if self.backupDestinations == 'local':
command = 'restic init --repo %s --password-file %s' % (self.repoPath, self.passwordFile)
ProcessUtilities.executioner(command, self.website.externalApp)
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)
ProcessUtilities.executioner(command)
logging.statusWriter(self.statusPath, 'Repo %s initiated for %s.' % (self.backupDestinations, self.website.domain), 1)
return 1
except BaseException, msg:
logging.statusWriter(self.statusPath,'%s. [IncJobs.initiateRepo.47][5009]' % str(msg), 1)
return 0
def createBackup(self):
self.statusPath = self.extraArgs['tempPath']
website = self.extraArgs['website']
self.backupDestinations = self.extraArgs['backupDestinations']
websiteData = self.extraArgs['websiteData']
websiteEmails = self.extraArgs['websiteEmails']
websiteSSLs = self.extraArgs['websiteSSLs']
websiteDatabases = self.extraArgs['websiteDatabases']
self.website = Websites.objects.get(domain=website)
newJob = IncJob(website=self.website)
newJob.save()
self.jobid = newJob
self.passwordFile = '/home/%s/%s' % (self.website.domain, self.website.domain)
password = randomPassword.generate_pass()
self.repoPath = '/home/%s/incbackup' % (self.website.domain)
if not os.path.exists(self.passwordFile):
command = 'echo "%s" > %s' % (password, self.passwordFile)
ProcessUtilities.executioner(command, self.website.externalApp)
if self.initiateRepo() == 0:
return
if self.prepareBackupMeta() == 0:
return
if websiteData:
if self.backupData() == 0:
return
if websiteDatabases:
if self.backupDatabases() == 0:
return
if websiteEmails:
if self.emailBackup() == 0:
return
logging.statusWriter(self.statusPath, 'Completed', 1)

View File

@ -0,0 +1,541 @@
#!/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
import threading as multi
from plogical.processUtilities import ProcessUtilities
from models import IncJob, JobSnapshots
from websiteFunctions.models import Websites
import plogical.randomPassword as randomPassword
from plogical.CyberCPLogFileWriter import CyberCPLogFileWriter as logging
from xml.etree.ElementTree import Element, SubElement
from xml.etree import ElementTree
from xml.dom import minidom
from backup.models import DBUsers
import plogical.mysqlUtilities as mysqlUtilities
from plogical.backupUtilities import backupUtilities
from plogical.dnsUtilities import DNS
from mailServer.models import Domains as eDomains
from random import randint
try:
from plogical.virtualHostUtilities import virtualHostUtilities
from plogical.mailUtilities import mailUtilities
except:
pass
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 = ''
def run(self):
if self.function == 'createBackup':
self.createBackup()
elif self.function == 'restorePoint':
self.restorePoint()
def restoreData(self):
try:
if self.jobid.destination == 'local':
repoLocation = '/home/%s/incbackup' % (self.website)
command = 'restic -r %s restore %s --target / --password-file %s' % (repoLocation, self.jobid.snapshotid, self.passwordFile)
result = ProcessUtilities.outputExecutioner(command)
logging.statusWriter(self.statusPath, result, 1)
elif self.jobid.destination[:4] == 'sftp':
repoLocation = '/home/backup/%s' % (self.website)
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)
except BaseException, msg:
logging.statusWriter(self.statusPath, "%s [46][5009]" % (str(msg)), 1)
return 0
def restoreDatabase(self):
try:
if self.jobid.destination == 'local':
repoLocation = '/home/%s/incbackup' % (self.website)
command = 'restic -r %s restore %s --target / --password-file %s' % (repoLocation, self.jobid.snapshotid, self.passwordFile)
result = ProcessUtilities.outputExecutioner(command)
logging.statusWriter(self.statusPath, result, 1)
elif self.jobid.destination[:4] == 'sftp':
repoLocation = '/home/backup/%s' % (self.website)
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)
if mysqlUtilities.mysqlUtilities.restoreDatabaseBackup(self.jobid.type.split(':')[1], '/home/cyberpanel', 'dummy', 'dummy') == 0:
raise BaseException
try:
os.remove('/home/cyberpanel/%s' % (self.jobid.type.split(':')[1]))
except:
pass
except BaseException, msg:
logging.statusWriter(self.statusPath, "%s [46][5009]" % (str(msg)), 1)
return 0
def restoreEmail(self):
try:
if self.jobid.destination == 'local':
repoLocation = '/home/%s/incbackup' % (self.website)
command = 'restic -r %s restore %s --target / --password-file %s' % (repoLocation, self.jobid.snapshotid, self.passwordFile)
result = ProcessUtilities.outputExecutioner(command)
logging.statusWriter(self.statusPath, result, 1)
elif self.jobid.destination[:4] == 'sftp':
repoLocation = '/home/backup/%s' % (self.website)
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)
except BaseException, msg:
logging.statusWriter(self.statusPath, "%s [46][5009]" % (str(msg)), 1)
return 0
def restorePoint(self):
try:
self.statusPath = self.extraArgs['tempPath']
self.website = self.extraArgs['website']
jobid = self.extraArgs['jobid']
self.jobid = JobSnapshots.objects.get(pk=jobid)
message = 'Starting restore of %s for %s.' % (self.jobid.snapshotid, self.website)
logging.statusWriter(self.statusPath, message, 1)
self.passwordFile = '/home/%s/%s' % (self.website, self.website)
## Restore Meta first
metaPathNew = '/home/%s/meta.xml' % (self.website)
if self.jobid.destination == 'local':
repoLocation = '/home/%s/incbackup' % (self.website)
command = 'restic -r %s restore latest --target / --password-file %s --include %s' % (repoLocation, self.passwordFile, metaPathNew)
result = ProcessUtilities.outputExecutioner(command)
logging.statusWriter(self.statusPath, result, 1)
elif self.jobid.destination[:4] == 'sftp':
repoLocation = '/home/backup/%s' % (self.website)
command = 'export PATH=${PATH}:/usr/bin && restic -r %s:%s restore latest --target / --password-file %s --include %s' % (self.jobid.destination, repoLocation, self.passwordFile, metaPathNew)
result = ProcessUtilities.outputExecutioner(command)
logging.statusWriter(self.statusPath, result, 1)
## Reconstruct configs configs
if self.extraArgs['reconstruct']:
execPath = "nice -n 10 /usr/local/CyberCP/bin/python2 " + virtualHostUtilities.cyberPanel + "/IncBackups/restoreMeta.py"
execPath = execPath + " submitRestore --metaPath %s --statusFile %s" % (metaPathNew, self.statusPath)
ProcessUtilities.outputExecutioner(execPath)
##
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':
self.restoreData()
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)
logging.statusWriter(self.statusPath, 'Completed', 1)
except BaseException, msg:
logging.statusWriter(self.extraArgs['tempPath'], str(msg), 1)
def prepareBackupMeta(self):
try:
######### Generating meta
## XML Generation
metaFileXML = Element('metaFile')
child = SubElement(metaFileXML, 'masterDomain')
child.text = self.website.domain
child = SubElement(metaFileXML, 'phpSelection')
child.text = self.website.phpSelection
child = SubElement(metaFileXML, 'externalApp')
child.text = self.website.externalApp
childDomains = self.website.childdomains_set.all()
databases = self.website.databases_set.all()
## Child domains XML
childDomainsXML = Element('ChildDomains')
for items in childDomains:
childDomainXML = Element('domain')
child = SubElement(childDomainXML, 'domain')
child.text = items.domain
child = SubElement(childDomainXML, 'phpSelection')
child.text = items.phpSelection
child = SubElement(childDomainXML, 'path')
child.text = items.path
childDomainsXML.append(childDomainXML)
metaFileXML.append(childDomainsXML)
## Databases XML
databasesXML = Element('Databases')
for items in databases:
try:
dbuser = DBUsers.objects.get(user=items.dbUser)
userToTry = items.dbUser
except:
dbusers = DBUsers.objects.all().filter(user=items.dbUser)
userToTry = items.dbUser
for it in dbusers:
dbuser = it
break
userToTry = mysqlUtilities.mysqlUtilities.fetchuser(items.dbUser)
try:
dbuser = DBUsers.objects.get(user=userToTry)
except:
dbusers = DBUsers.objects.all().filter(user=userToTry)
for it in dbusers:
dbuser = it
break
databaseXML = Element('database')
child = SubElement(databaseXML, 'dbName')
child.text = items.dbName
child = SubElement(databaseXML, 'dbUser')
child.text = userToTry
child = SubElement(databaseXML, 'password')
child.text = dbuser.password
databasesXML.append(databaseXML)
metaFileXML.append(databasesXML)
## Get Aliases
aliasesXML = Element('Aliases')
aliases = backupUtilities.getAliases(self.website.domain)
for items in aliases:
child = SubElement(aliasesXML, 'alias')
child.text = items
metaFileXML.append(aliasesXML)
## Finish Alias
## DNS Records XML
try:
dnsRecordsXML = Element("dnsrecords")
dnsRecords = DNS.getDNSRecords(self.website.domain)
for items in dnsRecords:
dnsRecordXML = Element('dnsrecord')
child = SubElement(dnsRecordXML, 'type')
child.text = items.type
child = SubElement(dnsRecordXML, 'name')
child.text = items.name
child = SubElement(dnsRecordXML, 'content')
child.text = items.content
child = SubElement(dnsRecordXML, 'priority')
child.text = str(items.prio)
dnsRecordsXML.append(dnsRecordXML)
metaFileXML.append(dnsRecordsXML)
except BaseException, msg:
logging.statusWriter(self.statusPath, '%s. [158:prepMeta]' % (str(msg)), 1)
## Email accounts XML
try:
emailRecordsXML = Element('emails')
eDomain = eDomains.objects.get(domain=self.website.domain)
emailAccounts = eDomain.eusers_set.all()
for items in emailAccounts:
emailRecordXML = Element('emailAccount')
child = SubElement(emailRecordXML, 'email')
child.text = items.email
child = SubElement(emailRecordXML, 'password')
child.text = items.password
emailRecordsXML.append(emailRecordXML)
metaFileXML.append(emailRecordsXML)
except BaseException, msg:
logging.statusWriter(self.statusPath, '%s. [warning:179:prepMeta]' % (str(msg)), 1)
## Email meta generated!
def prettify(elem):
"""Return a pretty-printed XML string for the Element.
"""
rough_string = ElementTree.tostring(elem, 'utf-8')
reparsed = minidom.parseString(rough_string)
return reparsed.toprettyxml(indent=" ")
## /home/example.com/backup/backup-example.com-02.13.2018_10-24-52/meta.xml -- metaPath
metaPath = '/home/cyberpanel/%s' % (str(randint(1000, 9999)))
xmlpretty = prettify(metaFileXML).encode('ascii', 'ignore')
metaFile = open(metaPath, 'w')
metaFile.write(xmlpretty)
metaFile.close()
os.chmod(metaPath, 0640)
## meta generated
logging.statusWriter(self.statusPath, 'Meta data is ready..', 1)
metaPathNew = '/home/%s/meta.xml' % (self.website.domain)
command = 'mv %s %s' % (metaPath, metaPathNew)
ProcessUtilities.executioner(command)
return 1
except BaseException, msg:
logging.statusWriter(self.statusPath, "%s [207][5009]" % (str(msg)), 1)
return 0
def backupData(self):
try:
logging.statusWriter(self.statusPath, 'Backing up data..', 1)
if self.backupDestinations == 'local':
backupPath = '/home/%s' % (self.website.domain)
command = 'restic -r %s backup %s --password-file %s --exclude %s' % (self.repoPath, backupPath, self.passwordFile, self.repoPath)
result = ProcessUtilities.outputExecutioner(command)
logging.statusWriter(self.statusPath, result, 1)
snapShotid = result.split(' ')[-2]
newSnapshot = JobSnapshots(job=self.jobid, type='data:%s' % (backupPath), snapshotid=snapShotid, destination=self.backupDestinations)
newSnapshot.save()
elif self.backupDestinations[:4] == 'sftp':
remotePath = '/home/backup/%s' % (self.website.domain)
backupPath = '/home/%s' % (self.website.domain)
command = 'export PATH=${PATH}:/usr/bin && restic -r %s:%s backup %s --password-file %s --exclude %s' % (self.backupDestinations, remotePath, backupPath, self.passwordFile, self.repoPath)
result = ProcessUtilities.outputExecutioner(command)
logging.statusWriter(self.statusPath, result, 1)
snapShotid = result.split(' ')[-2]
newSnapshot = JobSnapshots(job=self.jobid, type='data:%s' % (remotePath), snapshotid=snapShotid,
destination=self.backupDestinations)
newSnapshot.save()
logging.statusWriter(self.statusPath, 'Data for %s backed to %s.' % (self.website.domain, self.backupDestinations), 1)
return 1
except BaseException, msg:
logging.statusWriter(self.statusPath,'%s. [IncJobs.backupData.223][5009]' % str(msg), 1)
return 0
def backupDatabases(self):
try:
logging.statusWriter(self.statusPath, 'Backing up databases..', 1)
databases = self.website.databases_set.all()
for items in databases:
if mysqlUtilities.mysqlUtilities.createDatabaseBackup(items.dbName, '/home/cyberpanel') == 0:
return 0
dbPath = '/home/cyberpanel/%s.sql' % (items.dbName)
if self.backupDestinations == 'local':
command = 'restic -r %s backup %s --password-file %s' % (self.repoPath, dbPath, self.passwordFile)
result = ProcessUtilities.outputExecutioner(command)
logging.statusWriter(self.statusPath, result, 1)
snapShotid = result.split(' ')[-2]
newSnapshot = JobSnapshots(job=self.jobid, type='database:%s' % (items.dbName), snapshotid=snapShotid, destination=self.backupDestinations)
newSnapshot.save()
elif self.backupDestinations[:4] == 'sftp':
remotePath = '/home/backup/%s' % (self.website.domain)
command = 'export PATH=${PATH}:/usr/bin && restic -r %s:%s backup %s --password-file %s --exclude %s' % (
self.backupDestinations, remotePath, dbPath, self.passwordFile, self.repoPath)
result = ProcessUtilities.outputExecutioner(command)
logging.statusWriter(self.statusPath, result, 1)
snapShotid = result.split(' ')[-2]
newSnapshot = JobSnapshots(job=self.jobid, type='database:%s' % (items.dbName), snapshotid=snapShotid,
destination=self.backupDestinations)
newSnapshot.save()
try:
os.remove('/home/cyberpanel/%s' % (items.dbName))
except:
pass
return 1
except BaseException, msg:
logging.statusWriter(self.statusPath,'%s. [IncJobs.backupDatabases.269][5009]' % str(msg), 1)
return 0
def emailBackup(self):
try:
logging.statusWriter(self.statusPath, 'Backing up emails..', 1)
backupPath = '/home/vmail/%s' % (self.website.domain)
if self.backupDestinations == 'local':
command = 'restic -r %s backup %s --password-file %s' % (
self.repoPath, backupPath, self.passwordFile)
result = ProcessUtilities.outputExecutioner(command)
logging.statusWriter(self.statusPath, result, 1)
snapShotid = result.split(' ')[-2]
newSnapshot = JobSnapshots(job=self.jobid, type='email:%s' % (backupPath), snapshotid=snapShotid,
destination=self.backupDestinations)
newSnapshot.save()
elif self.backupDestinations[:4] == 'sftp':
remotePath = '/home/backup/%s' % (self.website.domain)
command = 'export PATH=${PATH}:/usr/bin && restic -r %s:%s backup %s --password-file %s --exclude %s' % (
self.backupDestinations, remotePath, backupPath, self.passwordFile, self.repoPath)
result = ProcessUtilities.outputExecutioner(command)
logging.statusWriter(self.statusPath, result, 1)
snapShotid = result.split(' ')[-2]
newSnapshot = JobSnapshots(job=self.jobid, type='email:%s' % (backupPath), snapshotid=snapShotid,
destination=self.backupDestinations)
newSnapshot.save()
logging.statusWriter(self.statusPath, 'Emails for %s backed to %s.' % (self.website.domain, self.backupDestinations), 1)
return 1
except BaseException, msg:
logging.statusWriter(self.statusPath,'%s. [IncJobs.emailBackup.269][5009]' % str(msg), 1)
return 0
def initiateRepo(self):
try:
logging.statusWriter(self.statusPath, 'Will first initiate backup repo..', 1)
if self.backupDestinations == 'local':
command = 'restic init --repo %s --password-file %s' % (self.repoPath, self.passwordFile)
result = ProcessUtilities.outputExecutioner(command)
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)
logging.statusWriter(self.statusPath, result, 1)
else:
logging.statusWriter(self.statusPath, 'AWS implementation is currently pending. [5009]', 1)
return 0
logging.statusWriter(self.statusPath, 'Repo %s initiated for %s.' % (self.backupDestinations, self.website.domain), 1)
return 1
except BaseException, msg:
logging.statusWriter(self.statusPath,'%s. [IncJobs.initiateRepo.47][5009]' % str(msg), 1)
return 0
def createBackup(self):
self.statusPath = self.extraArgs['tempPath']
website = self.extraArgs['website']
self.backupDestinations = self.extraArgs['backupDestinations']
websiteData = self.extraArgs['websiteData']
websiteEmails = self.extraArgs['websiteEmails']
websiteSSLs = self.extraArgs['websiteSSLs']
websiteDatabases = self.extraArgs['websiteDatabases']
self.website = Websites.objects.get(domain=website)
newJob = IncJob(website=self.website)
newJob.save()
self.jobid = newJob
self.passwordFile = '/home/%s/%s' % (self.website.domain, self.website.domain)
self.repoPath = '/home/%s/incbackup' % (self.website.domain)
if not os.path.exists(self.passwordFile):
password = randomPassword.generate_pass()
command = 'echo "%s" > %s' % (password, self.passwordFile)
ProcessUtilities.executioner(command, self.website.externalApp)
if self.initiateRepo() == 0:
return
if self.prepareBackupMeta() == 0:
return
if websiteData:
if self.backupData() == 0:
return
if websiteDatabases:
if self.backupDatabases() == 0:
return
if websiteEmails:
if self.emailBackup() == 0:
return
## meta generated
logging.statusWriter(self.statusPath, 'Taking backup of meta file, this file can be used to reconstruct at later point..', 1)
metaPathNew = '/home/%s/meta.xml' % (self.website.domain)
if self.backupDestinations == 'local':
command = 'restic -r %s backup %s --password-file %s' % (
self.repoPath, metaPathNew, self.passwordFile)
result = ProcessUtilities.outputExecutioner(command)
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 -r %s:%s backup %s --password-file %s --exclude %s' % (
self.backupDestinations, remotePath, metaPathNew, self.passwordFile, self.repoPath)
result = ProcessUtilities.outputExecutioner(command)
logging.statusWriter(self.statusPath, result, 1)
try:
os.remove(metaPathNew)
except:
pass
logging.statusWriter(self.statusPath, 'Completed', 1)

0
IncBackups/__init__.py Normal file
View File

6
IncBackups/admin.py Normal file
View File

@ -0,0 +1,6 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.contrib import admin
# Register your models here.

8
IncBackups/apps.py Normal file
View File

@ -0,0 +1,8 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.apps import AppConfig
class IncbackupsConfig(AppConfig):
name = 'IncBackups'

View File

15
IncBackups/models.py Normal file
View File

@ -0,0 +1,15 @@
from __future__ import unicode_literals
from django.db import models
from websiteFunctions.models import Websites
from datetime import datetime
class IncJob(models.Model):
website = models.ForeignKey(Websites)
date = models.DateTimeField(default=datetime.now, blank=True)
class JobSnapshots(models.Model):
job = models.ForeignKey(IncJob)
type = models.CharField(max_length=300)
snapshotid = models.CharField(max_length=50)
destination = models.CharField(max_length=200, default='')

167
IncBackups/restoreMeta.py Normal file
View File

@ -0,0 +1,167 @@
#!/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 websiteFunctions.models import Websites
from plogical.CyberCPLogFileWriter import CyberCPLogFileWriter as logging
from xml.etree import ElementTree
import plogical.mysqlUtilities as mysqlUtilities
from databases.models import Databases
import argparse
try:
from plogical.virtualHostUtilities import virtualHostUtilities
from plogical.mailUtilities import mailUtilities
except:
pass
class restoreMeta():
@staticmethod
def startRestore(metaPath, statusPath):
try:
## extracting master domain for later use
backupMetaData = ElementTree.parse(metaPath)
masterDomain = backupMetaData.find('masterDomain').text
########### Creating child/sub/addon/parked domains
logging.statusWriter(statusPath, "Creating Child Domains!", 1)
### Restoring Child Domains if any.
childDomains = backupMetaData.findall('ChildDomains/domain')
try:
for childDomain in childDomains:
domain = childDomain.find('domain').text
phpSelection = childDomain.find('phpSelection').text
path = childDomain.find('path').text
virtualHostUtilities.createDomain(masterDomain, domain, phpSelection, path, 0, 0, 0,
'admin', 0)
except BaseException, msg:
logging.writeToFile(str(msg) + " [startRestore]")
return 0
## Restore Aliases
logging.statusWriter(statusPath, "Restoring Domain Aliases!", 1)
aliases = backupMetaData.findall('Aliases/alias')
for items in aliases:
virtualHostUtilities.createAlias(masterDomain, items.text, 0, "", "", "admin")
## Restoring email accounts
logging.statusWriter(statusPath, "Restoring email accounts!", 1)
emailAccounts = backupMetaData.findall('emails/emailAccount')
try:
for emailAccount in emailAccounts:
email = emailAccount.find('email').text
username = email.split("@")[0]
password = emailAccount.find('password').text
result = mailUtilities.createEmailAccount(masterDomain, username, password)
if result[0] == 0:
logging.statusWriter(statusPath, 'Email existed, updating password according to last snapshot. %s' % (email))
if mailUtilities.changeEmailPassword(email, password, 1)[0] == 0:
logging.statusWriter(statusPath,
'Failed changing password for: %s' % (
email))
else:
logging.statusWriter(statusPath,
'Password changed for: %s' % (
email))
else:
logging.statusWriter(statusPath,
'Email created: %s' % (
email))
except BaseException, msg:
logging.writeToFile(str(msg) + " [startRestore]")
return 0
## Emails restored
## restoring databases
logging.statusWriter(statusPath, "Restoring Databases!", 1)
## Create databases
databases = backupMetaData.findall('Databases/database')
website = Websites.objects.get(domain=masterDomain)
for database in databases:
dbName = database.find('dbName').text
dbUser = database.find('dbUser').text
dbPassword = database.find('password').text
try:
dbExist = Databases.objects.get(dbName=dbName)
logging.statusWriter(statusPath, 'Database exists, changing Database password.. %s' % (dbName))
mysqlUtilities.mysqlUtilities.changePassword(dbUser, dbPassword, 1)
if mysqlUtilities.mysqlUtilities.changePassword(dbUser, dbPassword, 1) == 0:
logging.statusWriter(statusPath, 'Failed changing password for database: %s' % (dbName))
else:
logging.statusWriter(statusPath, 'Password successfully changed for database: %s.' % (dbName))
except:
logging.statusWriter(statusPath, 'Database did not exist, creating new.. %s' % (dbName))
if mysqlUtilities.mysqlUtilities.createDatabase(dbName, dbUser, "cyberpanel") == 0:
logging.statusWriter(statusPath, 'Failed the creation of database: %s' % (dbName))
else:
logging.statusWriter(statusPath, 'Database: %s successfully created.' % (dbName))
try:
newDB = Databases(website=website, dbName=dbName, dbUser=dbUser)
newDB.save()
except:
pass
## Databases restored
try:
os.remove(metaPath)
except:
pass
except BaseException, msg:
logging.writeToFile(str(msg) + " [startRestore]")
def main():
parser = argparse.ArgumentParser(description='CyberPanel Installer')
parser.add_argument('function', help='Specific a function to call!')
parser.add_argument('--metaPath', help='')
parser.add_argument('--statusFile', help='!')
## backup restore arguments
parser.add_argument('--backupFile', help='')
parser.add_argument('--dir', help='')
args = parser.parse_args()
if args.function == "submitRestore":
restoreMeta.startRestore(args.metaPath,args.statusFile)
if __name__ == "__main__":
main()

View File

@ -0,0 +1,494 @@
//*** Backup site ****//
app.controller('createIncrementalBackups', function ($scope, $http, $timeout) {
$scope.destination = true;
$scope.backupButton = true;
$scope.cyberpanelLoading = true;
$scope.runningBackup = true;
$scope.restoreSt = true;
$scope.fetchDetails = function () {
getBackupStatus();
$scope.populateCurrentRecords();
$scope.destination = false;
$scope.runningBackup = true;
};
function getBackupStatus() {
$scope.cyberpanelLoadingBottom = false;
url = "/IncrementalBackups/getBackupStatus";
var data = {
websiteToBeBacked: $scope.websiteToBeBacked,
tempPath: $scope.tempPath
};
var config = {
headers: {
'X-CSRFToken': getCookie('csrftoken')
}
};
$http.post(url, data, config).then(ListInitialDatas, cantLoadInitialDatas);
function ListInitialDatas(response) {
if (response.data.backupStatus === 1) {
if (response.data.abort === 1) {
$timeout.cancel();
$scope.cyberpanelLoadingBottom = true;
$scope.destination = false;
$scope.runningBackup = false;
$scope.backupButton = false;
$scope.cyberpanelLoading = true;
$scope.fileName = response.data.fileName;
$scope.status = response.data.status;
$scope.populateCurrentRecords();
return;
} else {
$scope.destination = true;
$scope.backupButton = true;
$scope.runningBackup = false;
$scope.fileName = response.data.fileName;
$scope.status = response.data.status;
$timeout(getBackupStatus, 2000);
}
} else {
$timeout.cancel();
$scope.cyberpanelLoadingBottom = true;
$scope.cyberpanelLoading = true;
$scope.backupButton = false;
}
}
function cantLoadInitialDatas(response) {
}
}
$scope.destinationSelection = function () {
$scope.backupButton = false;
};
$scope.populateCurrentRecords = function () {
url = "/IncrementalBackups/fetchCurrentBackups";
var data = {
websiteToBeBacked: $scope.websiteToBeBacked,
};
var config = {
headers: {
'X-CSRFToken': getCookie('csrftoken')
}
};
$http.post(url, data, config).then(ListInitialDatas, cantLoadInitialDatas);
function ListInitialDatas(response) {
if (response.data.status === 1) {
$scope.records = JSON.parse(response.data.data);
} else {
new PNotify({
title: 'Error!',
text: response.data.error_message,
type: 'error'
});
}
}
function cantLoadInitialDatas(response) {
new PNotify({
title: 'Operation Failed!',
text: 'Could not connect to server, please refresh this page',
type: 'error'
});
}
};
$scope.createBackup = function () {
$scope.status = '';
$scope.cyberpanelLoading = false;
url = "/IncrementalBackups/submitBackupCreation";
var data = {
websiteToBeBacked: $scope.websiteToBeBacked,
backupDestinations: $scope.backupDestinations,
websiteData: $scope.websiteData,
websiteEmails: $scope.websiteEmails,
websiteSSLs: $scope.websiteSSLs,
websiteDatabases: $scope.websiteDatabases
};
var config = {
headers: {
'X-CSRFToken': getCookie('csrftoken')
}
};
$http.post(url, data, config).then(ListInitialDatas, cantLoadInitialDatas);
function ListInitialDatas(response) {
if (response.data.status === 1) {
$scope.tempPath = response.data.tempPath;
getBackupStatus();
}else{
new PNotify({
title: 'Operation Failed!',
text: response.data.error_message,
type: 'error'
});
}
}
function cantLoadInitialDatas(response) {
}
};
$scope.deleteBackup = function (id) {
url = "/IncrementalBackups/deleteBackup";
var data = {
backupID: id,
websiteToBeBacked: $scope.websiteToBeBacked
};
var config = {
headers: {
'X-CSRFToken': getCookie('csrftoken')
}
};
$http.post(url, data, config).then(ListInitialDatas, cantLoadInitialDatas);
function ListInitialDatas(response) {
if (response.data.status === 1) {
$scope.populateCurrentRecords();
}else{
new PNotify({
title: 'Operation Failed!',
text: response.data.error_message,
type: 'error'
});
}
}
function cantLoadInitialDatas(response) {
}
};
$scope.restore = function (id) {
$scope.cyberpanelLoading = false;
url = "/IncrementalBackups/fetchRestorePoints";
var data = {
id: id,
websiteToBeBacked: $scope.websiteToBeBacked
};
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.jobs = JSON.parse(response.data.data);
} 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.restorePoint = function (id, reconstruct) {
$scope.status = '';
$scope.cyberpanelLoading = false;
$scope.restoreSt = false;
url = "/IncrementalBackups/restorePoint";
var data = {
websiteToBeBacked: $scope.websiteToBeBacked,
jobid : id,
reconstruct: reconstruct
};
var config = {
headers: {
'X-CSRFToken': getCookie('csrftoken')
}
};
$http.post(url, data, config).then(ListInitialDatas, cantLoadInitialDatas);
function ListInitialDatas(response) {
if (response.data.status === 1) {
$scope.tempPath = response.data.tempPath;
getBackupStatus();
}
}
function cantLoadInitialDatas(response) {
}
};
});
///** Backup site ends **///
app.controller('incrementalDestinations', function ($scope, $http) {
$scope.cyberpanelLoading = true;
$scope.sftpHide = true;
$scope.awsHide = true;
$scope.fetchDetails = function () {
if ($scope.destinationType === 'SFTP') {
$scope.sftpHide = false;
$scope.populateCurrentRecords();
} else {
$scope.sftpHide = true;
$scope.awsHide = false;
$scope.populateCurrentRecords();
}
};
$scope.populateCurrentRecords = function () {
$scope.cyberpanelLoading = false;
url = "/IncrementalBackups/populateCurrentRecords";
var type = 'SFTP';
if ($scope.destinationType === 'SFTP') {
type = 'SFTP';
} else {
type = 'AWS';
}
var data = {
type: type
};
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);
} 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.addDestination = function (type) {
$scope.cyberpanelLoading = false;
url = "/IncrementalBackups/addDestination";
if (type === 'SFTP') {
var data = {
type: type,
IPAddress: $scope.IPAddress,
password: $scope.password,
backupSSHPort: $scope.backupSSHPort
};
} else {
var data = {
type: type,
AWS_ACCESS_KEY_ID: $scope.AWS_ACCESS_KEY_ID,
AWS_SECRET_ACCESS_KEY: $scope.AWS_SECRET_ACCESS_KEY,
};
}
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 added.',
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.removeDestination = function (type, ipAddress) {
$scope.cyberpanelLoading = false;
url = "/IncrementalBackups/removeDestination";
var data = {
type: type,
IPAddress: ipAddress,
};
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'
});
}
};
});

View File

@ -0,0 +1,229 @@
{% extends "baseTemplate/index.html" %}
{% load i18n %}
{% block title %}{% trans "Create Incremental Backup" %}{% endblock %}
{% block content %}
{% load static %}
{% get_current_language as LANGUAGE_CODE %}
<!-- Current language: {{ LANGUAGE_CODE }} -->
<div class="container">
<div id="page-title">
<h2>{% trans "Back up Website" %} - <a target="_blank" href="http://go.cyberpanel.net/backup"
style="height: 23px;line-height: 21px;"
class="btn btn-border btn-alt border-red btn-link font-red" title=""><span>{% trans "Backup Docs" %}</span></a>
</h2>
<p>{% trans "This page can be used to create incremental backups for your websites." %}</p>
</div>
<div ng-controller="createIncrementalBackups" class="panel">
<div class="panel-body">
<h3 class="title-hero">
{% trans "Back up Website" %} <img ng-hide="cyberpanelLoading"
src="{% static 'images/loading.gif' %}">
</h3>
<div class="example-box-wrapper">
<form action="/" class="form-horizontal bordered-row">
<div class="form-group">
<label class="col-sm-3 control-label">{% trans "Select Website" %} </label>
<div class="col-sm-6">
<select ng-change="fetchDetails()" ng-model="websiteToBeBacked" class="form-control">
{% for items in websiteList %}
<option>{{ items }}</option>
{% endfor %}
</select>
</div>
</div>
<div ng-hide="destination" class="form-group">
<label class="col-sm-3 control-label">{% trans "Destination" %}</label>
<div class="col-sm-6">
<select ng-change="destinationSelection()" ng-model="backupDestinations"
class="form-control">
{% for items in destinations %}
<option>{{ items }}</option>
{% endfor %}
</select>
</div>
</div>
<div ng-hide="destination" 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>
<!---- if Back up is running ----->
<div ng-hide="runningBackup" class="form-group">
<div class="col-sm-12">
<div class="col-sm-12">
<textarea ng-model="status" class="form-control" rows="10"></textarea>
</div>
</div>
</div>
<!---- if Back up is running------>
<div ng-hide="backupButton" class="form-group">
<label class="col-sm-3 control-label"></label>
<div class="col-sm-4">
<button type="button" ng-click="createBackup()"
class="btn btn-primary btn-lg btn-block">{% trans "Create Back up" %}</button>
</div>
</div>
<!------ List of records --------------->
<div class="form-group">
<div class="col-sm-12">
<table class="table">
<thead>
<tr>
<th>{% trans "ID" %}</th>
<th>{% trans "Date" %}</th>
<th>{% trans "Restore" %}</th>
<th>{% trans "Delete" %}</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="record in records track by $index">
<td ng-bind="record.id"></td>
<td ng-bind="record.date"></td>
<td>
<a ng-click="restore(record.id)" data-toggle="modal" data-target="#settings"
ng-click='deleteCLPackage()'
class="btn btn-border btn-alt border-green btn-link font-green"
title=""><span>Restore Points</span></a>
<div id="settings" class="modal fade" role="dialog">
<div class="modal-dialog modal-lg">
<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">
&times;
</button>
<h4 class="modal-title">Restore Points
<img ng-hide="cyberpanelLoading"
src="{% static 'images/loading.gif' %}">
</h4>
</div>
<div class="modal-body">
<table class="table">
<thead>
<tr>
<th>{% trans "Job ID" %}</th>
<th>{% trans "Snapshot ID" %}</th>
<th>{% trans "Type" %}</th>
<th>{% trans "Destination" %}</th>
<th>{% trans "Action" %}</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="job in jobs track by $index">
<td ng-bind="job.id"></td>
<td ng-bind="job.snapshotid"></td>
<td ng-bind="job.type"></td>
<td ng-bind="job.destination"></td>
<td>
<a ng-click="restorePoint(job.id, 0)" class="btn btn-border btn-alt border-green btn-link font-green"
title=""><span>Restore</span></a>
<a ng-click="restorePoint(job.id, 1)" class="btn btn-border btn-alt border-green btn-link font-green"
title=""><span>Restore and Reconstruct</span></a>
</td>
</tr>
</tbody>
</table>
<div ng-hide="restoreSt" class="form-group">
<div class="col-sm-12">
<div class="col-sm-12">
<textarea ng-model="status"
class="form-control"
rows="7"></textarea>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" ng-disabled="savingSettings"
class="btn btn-default" data-dismiss="modal">
Close
</button>
</div>
</div>
</div>
</div>
</td>
<a href="">
<td ng-click="deleteBackup(record.id)"><img
src="{% static 'images/delete.png' %}"></td>
</a>
</tr>
</tbody>
</table>
</div>
</div>
<!------ List of records --------------->
</form>
</div>
</div>
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,186 @@
{% extends "baseTemplate/index.html" %}
{% load i18n %}
{% block title %}{% trans "Set up Back up Destinations" %}{% endblock %}
{% block content %}
{% load static %}
{% get_current_language as LANGUAGE_CODE %}
<!-- Current language: {{ LANGUAGE_CODE }} -->
<div class="container">
<div id="page-title">
<h2>{% trans "Set up Incremental Back up Destinations" %} - <a target="_blank"
href="http://go.cyberpanel.net/remote-backup"
style="height: 23px;line-height: 21px;"
class="btn btn-border btn-alt border-red btn-link font-red"
title=""><span>{% trans "Remote Backups" %}</span></a>
</h2>
<p>{% trans "On this page you can set up your Back up destinations. (SFTP and AWS)" %}</p>
</div>
<div ng-controller="incrementalDestinations" class="panel">
<div class="panel-body">
<h3 class="title-hero">
{% trans "Set up Back up Destinations." %} <img ng-hide="cyberpanelLoading"
src="{% static 'images/loading.gif' %}">
</h3>
<div class="example-box-wrapper">
<form action="/" class="form-horizontal bordered-row">
<div class="form-group">
<label class="col-sm-3 control-label">{% trans "Select Type" %} </label>
<div class="col-sm-6">
<select ng-change="fetchDetails()" ng-model="destinationType" class="form-control">
<option>SFTP</option>
<option>AWS</option>
</select>
</div>
</div>
<!--- SFTP --->
<div ng-hide="sftpHide" class="form-group">
<label class="col-sm-3 control-label">{% trans "IP Address" %}</label>
<div class="col-sm-6">
<input type="text" class="form-control" ng-model="IPAddress" required>
</div>
</div>
<div ng-hide="sftpHide" class="form-group">
<label class="col-sm-3 control-label">{% trans "Password" %}</label>
<div class="col-sm-6">
<input placeholder="" type="password" class="form-control" ng-model="password" required>
</div>
</div>
<div ng-hide="sftpHide" class="form-group">
<label class="col-sm-3 control-label">{% trans "Port" %}</label>
<div class="col-sm-6">
<input placeholder="{% trans "Backup server SSH Port, leave empty for 22." %}"
type="text" class="form-control" ng-model="backupSSHPort" required>
</div>
</div>
<div ng-hide="sftpHide" class="form-group">
<label class="col-sm-3 control-label"></label>
<div class="col-sm-4">
<button type="button" ng-click="addDestination('SFTP')"
class="btn btn-primary btn-lg btn-block">{% trans "Add Destination" %}</button>
</div>
</div>
<!--- SFTP --->
<!------ List of Destinations --------------->
<div ng-hide="sftpHide" class="form-group">
<div class="col-sm-12">
<table class="table">
<thead>
<tr>
<th>{% trans "IP" %}</th>
<th>{% trans "Port" %}</th>
<th>{% trans "Delete" %}</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="record in records track by $index">
<td ng-bind="record.ip"></td>
<td ng-bind="record.port"></td>
<td ng-click="removeDestination('SFTP',record.ip)"><img src="{% static 'images/delete.png' %}">
</td>
</tr>
</tbody>
</table>
</div>
</div>
<!------ List of records --------------->
<!--- SFTP End --->
<!--- AWS Start --->
<div ng-hide="awsHide" class="form-group">
<label class="col-sm-3 control-label">{% trans "AWS_ACCESS_KEY_ID" %}</label>
<div class="col-sm-6">
<input type="text" class="form-control" ng-model="AWS_ACCESS_KEY_ID" required>
</div>
</div>
<div ng-hide="awsHide" class="form-group">
<label class="col-sm-3 control-label">{% trans "AWS_SECRET_ACCESS_KEY" %}</label>
<div class="col-sm-6">
<input placeholder="" type="password" class="form-control" ng-model="AWS_SECRET_ACCESS_KEY" required>
</div>
</div>
<div ng-hide="awsHide" class="form-group">
<label class="col-sm-3 control-label"></label>
<div class="col-sm-4">
<button type="button" ng-click="addDestination('AWS')"
class="btn btn-primary btn-lg btn-block">{% trans "Add Destination" %}</button>
</div>
</div>
<!--- SFTP --->
<!------ List of Destinations --------------->
<div ng-hide="awsHide" class="form-group">
<div class="col-sm-12">
<table class="table">
<thead>
<tr>
<th>{% trans "AWS_ACCESS_KEY_ID" %}</th>
<th>{% trans "Delete" %}</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="record in records track by $index">
<td ng-bind="record.AWS_ACCESS_KEY_ID"></td>
<td ng-click="removeDestination('AWS', record.AWS_ACCESS_KEY_ID)"><img src="{% static 'images/delete.png' %}">
</td>
</tr>
</tbody>
</table>
</div>
</div>
<!------ List of records --------------->
<!--- AWS End --->
</form>
</div>
</div>
</div>
</div>
{% endblock %}

6
IncBackups/tests.py Normal file
View File

@ -0,0 +1,6 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.test import TestCase
# Create your tests here.

16
IncBackups/urls.py Normal file
View File

@ -0,0 +1,16 @@
from django.conf.urls import url
import views
urlpatterns = [
url(r'^createBackup$', views.createBackup, name='createBackupInc'),
url(r'^backupDestinations$', views.backupDestinations, name='backupDestinationsInc'),
url(r'^addDestination$', views.addDestination, name='addDestinationInc'),
url(r'^populateCurrentRecords$', views.populateCurrentRecords, name='populateCurrentRecordsInc'),
url(r'^removeDestination$', views.removeDestination, name='removeDestinationInc'),
url(r'^fetchCurrentBackups$', views.fetchCurrentBackups, name='fetchCurrentBackupsInc'),
url(r'^submitBackupCreation$', views.submitBackupCreation, name='submitBackupCreationInc'),
url(r'^getBackupStatus$', views.getBackupStatus, name='getBackupStatusInc'),
url(r'^deleteBackup$', views.deleteBackup, name='deleteBackupInc'),
url(r'^fetchRestorePoints$', views.fetchRestorePoints, name='fetchRestorePointsInc'),
url(r'^restorePoint$', views.restorePoint, name='restorePointInc'),
]

543
IncBackups/views.py Normal file
View File

@ -0,0 +1,543 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.shortcuts import render
from plogical.acl import ACLManager
from django.shortcuts import HttpResponse
from plogical.processUtilities import ProcessUtilities
from plogical.virtualHostUtilities import virtualHostUtilities
import json
import os
from loginSystem.models import Administrator
from websiteFunctions.models import Websites
from .models import IncJob, JobSnapshots
from .IncBackupsControl import IncJobs
from random import randint
import time
from plogical.CyberCPLogFileWriter import CyberCPLogFileWriter as logging
# Create your views here.
def defRenderer(request, templateName, args):
return render(request, templateName, args)
def createBackup(request):
try:
userID = request.session['userID']
currentACL = ACLManager.loadedACL(userID)
if ACLManager.currentContextPermission(currentACL, 'createBackup') == 0:
return ACLManager.loadError()
websitesName = ACLManager.findAllSites(currentACL, userID)
destinations = []
destinations.append('local')
path = '/home/cyberpanel/sftp'
for items in os.listdir(path):
destinations.append('sftp:%s' % (items))
for items in os.listdir(path):
destinations.append('s3:s3.amazonaws.com/%s' % (items))
return defRenderer(request, 'IncBackups/createBackup.html', {'websiteList': websitesName, 'destinations': destinations})
except BaseException, msg:
return HttpResponse(str(msg))
def backupDestinations(request):
try:
userID = request.session['userID']
currentACL = ACLManager.loadedACL(userID)
if ACLManager.currentContextPermission(currentACL, 'addDeleteDestinations') == 0:
return ACLManager.loadError()
return defRenderer(request, 'IncBackups/incrementalDestinations.html', {})
except BaseException, msg:
return HttpResponse(str(msg))
def addDestination(request):
try:
userID = request.session['userID']
currentACL = ACLManager.loadedACL(userID)
if ACLManager.currentContextPermission(currentACL, 'addDeleteDestinations') == 0:
return ACLManager.loadErrorJson('destStatus', 0)
data = json.loads(request.body)
if data['type'] == 'SFTP':
ipAddress = data['IPAddress']
password = data['password']
ipFile = '/home/cyberpanel/sftp/%s' % (ipAddress)
try:
port = data['backupSSHPort']
except:
port = "22"
if os.path.exists(ipFile):
final_dic = {'status': 0, 'error_message': 'This destination already exists.'}
final_json = json.dumps(final_dic)
return HttpResponse(final_json)
try:
os.mkdir('/home/cyberpanel/sftp')
except:
pass
execPath = "/usr/local/CyberCP/bin/python2 " + virtualHostUtilities.cyberPanel + "/plogical/backupUtilities.py"
execPath = execPath + " submitDestinationCreation --ipAddress " + ipAddress + " --password " \
+ password + " --port " + port
output = ProcessUtilities.outputExecutioner(execPath)
if output.find('1,') > -1:
content = '%s\n%s' % (ipAddress, port)
writeToFile = open(ipFile, 'w')
writeToFile.write(content)
writeToFile.close()
command = 'cat /root/.ssh/config'
currentConfig = ProcessUtilities.outputExecutioner(command)
tmpFile = '/home/cyberpanel/sshconfig'
writeToFile = open(tmpFile, 'w')
writeToFile.write(currentConfig)
content = """Host %s
IdentityFile ~/.ssh/cyberpanel
Port %s
""" % (ipAddress, port)
writeToFile.write(content)
writeToFile.close()
command = 'mv %s /root/.ssh/config' % (tmpFile)
ProcessUtilities.executioner(command)
command = 'chown root:root /root/.ssh/config'
ProcessUtilities.executioner(command)
final_dic = {'status': 1, 'error_message': 'None'}
final_json = json.dumps(final_dic)
return HttpResponse(final_json)
else:
final_dic = {'status': 0, 'error_message': output}
final_json = json.dumps(final_dic)
return HttpResponse(final_json)
else:
aws = '/home/cyberpanel/aws'
try:
os.mkdir(aws)
except:
pass
AWS_ACCESS_KEY_ID = data['AWS_ACCESS_KEY_ID']
AWS_SECRET_ACCESS_KEY = data['AWS_SECRET_ACCESS_KEY']
awsFile = '/home/cyberpanel/aws/%s' % (AWS_ACCESS_KEY_ID)
writeToFile = open(awsFile, 'w')
writeToFile.write(AWS_SECRET_ACCESS_KEY)
writeToFile.close()
final_dic = {'status': 1}
final_json = json.dumps(final_dic)
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 populateCurrentRecords(request):
try:
userID = request.session['userID']
currentACL = ACLManager.loadedACL(userID)
if ACLManager.currentContextPermission(currentACL, 'addDeleteDestinations') == 0:
return ACLManager.loadErrorJson('fetchStatus', 0)
data = json.loads(request.body)
if data['type'] == 'SFTP':
path = '/home/cyberpanel/sftp'
if os.path.exists(path):
json_data = "["
checker = 0
for items in os.listdir(path):
fullPath = '/home/cyberpanel/sftp/%s' % (items)
data = open(fullPath, 'r').readlines()
dic = {
'ip': data[0].strip('\n'),
'port': data[1],
}
if checker == 0:
json_data = json_data + json.dumps(dic)
checker = 1
else:
json_data = json_data + ',' + json.dumps(dic)
else:
final_json = json.dumps({'status': 1, 'error_message': "None", "data": ''})
return HttpResponse(final_json)
else:
path = '/home/cyberpanel/aws'
if os.path.exists(path):
json_data = "["
checker = 0
for items in os.listdir(path):
dic = {
'AWS_ACCESS_KEY_ID': items
}
if checker == 0:
json_data = json_data + json.dumps(dic)
checker = 1
else:
json_data = json_data + ',' + json.dumps(dic)
else:
final_json = json.dumps({'status': 1, 'error_message': "None", "data": ''})
return HttpResponse(final_json)
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 removeDestination(request):
try:
userID = request.session['userID']
currentACL = ACLManager.loadedACL(userID)
if ACLManager.currentContextPermission(currentACL, 'addDeleteDestinations') == 0:
return ACLManager.loadErrorJson('destStatus', 0)
data = json.loads(request.body)
ipAddress = data['IPAddress']
if data['type'] == 'SFTP':
ipFile = '/home/cyberpanel/sftp/%s' % (ipAddress)
else:
ipFile = '/home/cyberpanel/aws/%s' % (ipAddress)
os.remove(ipFile)
final_dic = {'status': 1, 'error_message': 'None'}
final_json = json.dumps(final_dic)
return HttpResponse(final_json)
except BaseException, msg:
final_dic = {'destStatus': 0, 'error_message': str(msg)}
final_json = json.dumps(final_dic)
return HttpResponse(final_json)
def fetchCurrentBackups(request):
try:
userID = request.session['userID']
currentACL = ACLManager.loadedACL(userID)
admin = Administrator.objects.get(pk=userID)
data = json.loads(request.body)
backupDomain = data['websiteToBeBacked']
if ACLManager.checkOwnership(backupDomain, admin, currentACL) == 1:
pass
else:
return ACLManager.loadErrorJson('fetchStatus', 0)
if ACLManager.checkOwnership(backupDomain, admin, currentACL) == 1:
pass
else:
return ACLManager.loadErrorJson()
website = Websites.objects.get(domain=backupDomain)
backups = website.incjob_set.all()
json_data = "["
checker = 0
for items in reversed(backups):
includes = ""
jobs = items.jobsnapshots_set.all()
for job in jobs:
includes = '%s,%s:%s' % (includes, job.type, job.snapshotid)
dic = {'id': items.id,
'date': str(items.date),
'includes': includes
}
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 submitBackupCreation(request):
try:
userID = request.session['userID']
currentACL = ACLManager.loadedACL(userID)
admin = Administrator.objects.get(pk=userID)
data = json.loads(request.body)
backupDomain = data['websiteToBeBacked']
backupDestinations = data['backupDestinations']
if ACLManager.checkOwnership(backupDomain, admin, currentACL) == 1:
pass
else:
return ACLManager.loadErrorJson('metaStatus', 0)
tempPath = "/home/cyberpanel/" + str(randint(1000, 9999))
try:
websiteData = data['websiteData']
except:
websiteData = False
try:
websiteEmails = data['websiteEmails']
except:
websiteEmails = False
try:
websiteSSLs = data['websiteSSLs']
except:
websiteSSLs = False
try:
websiteDatabases = data['websiteDatabases']
except:
websiteDatabases = False
extraArgs = {}
extraArgs['website'] = backupDomain
extraArgs['tempPath'] = tempPath
extraArgs['backupDestinations'] = backupDestinations
extraArgs['websiteData'] = websiteData
extraArgs['websiteEmails'] = websiteEmails
extraArgs['websiteSSLs'] = websiteSSLs
extraArgs['websiteDatabases'] = websiteDatabases
startJob = IncJobs('createBackup', extraArgs)
startJob.start()
time.sleep(2)
final_json = json.dumps({'status': 1, 'error_message': "None", 'tempPath': tempPath})
return HttpResponse(final_json)
except BaseException, msg:
logging.writeToFile(str(msg))
final_dic = {'status': 0, 'metaStatus': 0, 'error_message': str(msg)}
final_json = json.dumps(final_dic)
return HttpResponse(final_json)
def getBackupStatus(request):
try:
data = json.loads(request.body)
status = data['tempPath']
backupDomain = data['websiteToBeBacked']
userID = request.session['userID']
currentACL = ACLManager.loadedACL(userID)
admin = Administrator.objects.get(pk=userID)
if ACLManager.checkOwnership(backupDomain, admin, currentACL) == 1:
pass
else:
return ACLManager.loadErrorJson('fetchStatus', 0)
## file name read ends
if os.path.exists(status):
command = "sudo cat " + status
result = ProcessUtilities.outputExecutioner(command, 'cyberpanel')
if result.find("Completed") > -1:
### Removing Files
os.remove(status)
final_json = json.dumps(
{'backupStatus': 1, 'error_message': "None", "status": result, "abort": 1})
return HttpResponse(final_json)
elif result.find("[5009]") > -1:
## removing status file, so that backup can re-run
try:
os.remove(status)
except:
pass
final_json = json.dumps(
{'backupStatus': 1, 'error_message': "None", "status": result,
"abort": 1})
return HttpResponse(final_json)
else:
final_json = json.dumps(
{'backupStatus': 1, 'error_message': "None", "status": result,
"abort": 0})
return HttpResponse(final_json)
else:
final_json = json.dumps({'backupStatus': 1, 'error_message': "None", "status": 1, "abort": 0})
return HttpResponse(final_json)
except BaseException, msg:
final_dic = {'backupStatus': 0, 'error_message': str(msg)}
final_json = json.dumps(final_dic)
logging.writeToFile(str(msg) + " [backupStatus]")
return HttpResponse(final_json)
def deleteBackup(request):
try:
userID = request.session['userID']
currentACL = ACLManager.loadedACL(userID)
admin = Administrator.objects.get(pk=userID)
data = json.loads(request.body)
backupDomain = data['websiteToBeBacked']
if ACLManager.checkOwnership(backupDomain, admin, currentACL) == 1:
pass
else:
return ACLManager.loadErrorJson('fetchStatus', 0)
id = data['backupID']
IncJob.objects.get(id=id).delete()
final_dic = {'status': 1, 'error_message': 'None'}
final_json = json.dumps(final_dic)
return HttpResponse(final_json)
except BaseException, msg:
final_dic = {'destStatus': 0, 'error_message': str(msg)}
final_json = json.dumps(final_dic)
return HttpResponse(final_json)
def fetchRestorePoints(request):
try:
userID = request.session['userID']
currentACL = ACLManager.loadedACL(userID)
admin = Administrator.objects.get(pk=userID)
data = json.loads(request.body)
backupDomain = data['websiteToBeBacked']
if ACLManager.checkOwnership(backupDomain, admin, currentACL) == 1:
pass
else:
return ACLManager.loadErrorJson('fetchStatus', 0)
data = json.loads(request.body)
id = data['id']
incJob = IncJob.objects.get(id=id)
backups = incJob.jobsnapshots_set.all()
json_data = "["
checker = 0
for items in backups:
dic = {'id': items.id,
'snapshotid': items.snapshotid,
'type': items.type,
'destination': items.destination,
}
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 restorePoint(request):
try:
userID = request.session['userID']
currentACL = ACLManager.loadedACL(userID)
admin = Administrator.objects.get(pk=userID)
data = json.loads(request.body)
backupDomain = data['websiteToBeBacked']
jobid = data['jobid']
if ACLManager.checkOwnership(backupDomain, admin, currentACL) == 1:
pass
else:
return ACLManager.loadErrorJson('metaStatus', 0)
tempPath = "/home/cyberpanel/" + str(randint(1000, 9999))
extraArgs = {}
extraArgs['website'] = backupDomain
extraArgs['jobid'] = jobid
extraArgs['tempPath'] = tempPath
extraArgs['reconstruct'] = data['reconstruct']
startJob = IncJobs('restorePoint', extraArgs)
startJob.start()
time.sleep(2)
final_json = json.dumps({'status': 1, 'error_message': "None", 'tempPath': tempPath})
return HttpResponse(final_json)
except BaseException, msg:
logging.writeToFile(str(msg))
final_dic = {'status': 0, 'metaStatus': 0, 'error_message': str(msg)}
final_json = json.dumps(final_dic)
return HttpResponse(final_json)

View File

@ -23,17 +23,13 @@ Webhosting control panel that uses OpenLiteSpeed as web server.
* PHP 5.6
* PHP 7.0
* PHP 7.1
* PHP 7.2
# Installation Instructions
```
wget http://cyberpanel.net/install.tar.gz
tar zxf install.tar.gz
cd install
chmod +x install.py
python install.py [IP Address]
sh <(curl https://cyberpanel.net/install.sh || wget -O - https://cyberpanel.net/install.sh)
```
# Resources

View File

@ -10,7 +10,9 @@ urlpatterns = [
url(r'^loginAPI', views.loginAPI, name='loginAPI'),
url(r'^getUserInfo$', views.getUserInfo, name='getUserInfo'),
url(r'^changeUserPassAPI', views.changeUserPassAPI, name='changeUserPassAPI'),
url(r'^changePackageAPI', views.changePackageAPI, name='changePackageAPI'),
url(r'^fetchSSHkey', views.fetchSSHkey, name='fetchSSHkey'),
url(r'^remoteTransfer', views.remoteTransfer, name='remoteTransfer'),
@ -19,11 +21,7 @@ urlpatterns = [
url(r'^cancelRemoteTransfer', views.cancelRemoteTransfer, name='cancelRemoteTransfer'),
url(r'^cyberPanelVersion', views.cyberPanelVersion, name='cyberPanelVersion'),
url(r'^putSSHkey', views.putSSHkey, name='putSSHkey'),
url(r'^changeAdminPassword', views.changeAdminPassword, name='changeAdminPassword'),
url(r'^runAWSBackups$', views.runAWSBackups, name='runAWSBackups'),
]

View File

@ -6,21 +6,21 @@ from django.http import HttpResponse
from loginSystem.models import Administrator
from plogical.virtualHostUtilities import virtualHostUtilities
from plogical import hashPassword
from plogical.installUtilities import installUtilities
from packages.models import Package
from baseTemplate.views import renderBase
from random import randint
from websiteFunctions.models import Websites,ChildDomains
from websiteFunctions.models import Websites
import os
from baseTemplate.models import version
import subprocess
import shlex
import re
from plogical.mailUtilities import mailUtilities
from websiteFunctions.website import WebsiteManager
from s3Backups.s3Backups import S3Backups
from plogical.CyberCPLogFileWriter import CyberCPLogFileWriter as logging
from plogical.processUtilities import ProcessUtilities
from django.views.decorators.csrf import csrf_exempt
# Create your views here.
@csrf_exempt
def verifyConn(request):
try:
if request.method == 'POST':
@ -31,6 +31,11 @@ def verifyConn(request):
admin = Administrator.objects.get(userName=adminUser)
if admin.api == 0:
data_ret = {"verifyConn": 0, 'error_message': "API Access Disabled."}
json_data = json.dumps(data_ret)
return HttpResponse(json_data)
if hashPassword.check_password(admin.password, adminPass):
data_ret = {"verifyConn": 1}
json_data = json.dumps(data_ret)
@ -45,7 +50,23 @@ def verifyConn(request):
json_data = json.dumps(data_ret)
return HttpResponse(json_data)
@csrf_exempt
def createWebsite(request):
data = json.loads(request.body)
adminUser = data['adminUser']
admin = Administrator.objects.get(userName=adminUser)
if admin.api == 0:
data_ret = {"existsStatus": 0, 'createWebSiteStatus': 0,
'error_message': "API Access Disabled."}
json_data = json.dumps(data_ret)
return HttpResponse(json_data)
wm = WebsiteManager()
return wm.createWebsiteAPI(json.loads(request.body))
@csrf_exempt
def getUserInfo(request):
try:
if request.method == 'POST':
@ -53,74 +74,44 @@ def createWebsite(request):
adminUser = data['adminUser']
adminPass = data['adminPass']
domain = data['domainName']
adminEmail = data['ownerEmail']
packageName = data['packageName']
websiteOwner = data['websiteOwner']
ownerPassword = data['ownerPassword']
externalApp = "".join(re.findall("[a-zA-Z]+", domain))[:7]
data['ssl'] = 0
data['dkimCheck'] = 0
data['openBasedir'] = 1
phpSelection = "PHP 7.0"
username = data['username']
admin = Administrator.objects.get(userName=adminUser)
if admin.api == 0:
data_ret = {"status": 0, 'error_message': "API Access Disabled."}
json_data = json.dumps(data_ret)
return HttpResponse(json_data)
if hashPassword.check_password(admin.password, adminPass):
pass
else:
data_ret = {"existsStatus": 0, 'createWebSiteStatus': 0,
data_ret = {"status": 0,
'error_message': "Could not authorize access to API"}
json_data = json.dumps(data_ret)
return HttpResponse(json_data)
if adminEmail is None:
adminEmail = "usman@cyberpersons.com"
try:
websiteOwn = Administrator(userName=websiteOwner, password=hashPassword.hash_password(ownerPassword),
email=adminEmail, type=3, owner=admin.pk,
initWebsitesLimit=1)
websiteOwn.save()
except BaseException,msg:
pass
## Create Configurations
numberOfWebsites = str(Websites.objects.count() + ChildDomains.objects.count())
sslpath = "/home/" + domain + "/public_html"
## Create Configurations
execPath = "sudo python " + virtualHostUtilities.cyberPanel + "/plogical/virtualHostUtilities.py"
execPath = execPath + " createVirtualHost --virtualHostName " + domain + \
" --administratorEmail " + adminEmail + " --phpVersion '" + phpSelection + \
"' --virtualHostUser " + externalApp + " --numberOfSites " + numberOfWebsites + \
" --ssl " + str(data['ssl']) + " --sslPath " + sslpath + " --dkimCheck " + str(data['dkimCheck']) \
+ " --openBasedir " + str(data['openBasedir']) + ' --websiteOwner ' + websiteOwner \
+ ' --package ' + packageName
output = subprocess.check_output(shlex.split(execPath))
if output.find("1,None") > -1:
data_ret = {'createWebSiteStatus': 1, 'error_message': "None", "existsStatus": 0}
user = Administrator.objects.get(userName=username)
data_ret = {'status': 0,
'firstName': user.firstName,
'lastName': user.lastName,
'email': user.email,
'adminStatus': user.acl.adminStatus,
'error_message': "None"}
json_data = json.dumps(data_ret)
return HttpResponse(json_data)
else:
data_ret = {'createWebSiteStatus': 0, 'error_message': output, "existsStatus": 0}
except:
data_ret = {'status': 0, 'error_message': "User does not exists."}
json_data = json.dumps(data_ret)
return HttpResponse(json_data)
except BaseException, msg:
data_ret = {'createWebSiteStatus': 0, 'error_message': str(msg), "existsStatus": 0}
data_ret = {'status': 0, 'error_message': str(msg)}
json_data = json.dumps(data_ret)
return HttpResponse(json_data)
@csrf_exempt
def changeUserPassAPI(request):
try:
if request.method == 'POST':
@ -130,11 +121,17 @@ def changeUserPassAPI(request):
websiteOwner = data['websiteOwner']
ownerPassword = data['ownerPassword']
adminUser = data['adminUser']
adminPass = data['adminPass']
admin = Administrator.objects.get(userName=adminUser)
if admin.api == 0:
data_ret = {"changeStatus": 0, 'error_message': "API Access Disabled."}
json_data = json.dumps(data_ret)
return HttpResponse(json_data)
if hashPassword.check_password(admin.password, adminPass):
pass
else:
@ -159,6 +156,7 @@ def changeUserPassAPI(request):
json_data = json.dumps(data_ret)
return HttpResponse(json_data)
@csrf_exempt
def changePackageAPI(request):
try:
if request.method == 'POST':
@ -172,6 +170,11 @@ def changePackageAPI(request):
admin = Administrator.objects.get(userName=adminUser)
if admin.api == 0:
data_ret = {"changePackage": 0, 'error_message': "API Access Disabled."}
json_data = json.dumps(data_ret)
return HttpResponse(json_data)
if hashPassword.check_password(admin.password, adminPass):
pass
else:
@ -198,16 +201,24 @@ def changePackageAPI(request):
json_data = json.dumps(data_ret)
return HttpResponse(json_data)
@csrf_exempt
def deleteWebsite(request):
try:
if request.method == 'POST':
data = json.loads(request.body)
websiteName = data['domainName']
adminUser = data['adminUser']
adminPass = data['adminPass']
admin = Administrator.objects.get(userName=adminUser)
if admin.api == 0:
data_ret = {"websiteDeleteStatus": 0, 'error_message': "API Access Disabled."}
json_data = json.dumps(data_ret)
return HttpResponse(json_data)
data['websiteName'] = data['domainName']
if hashPassword.check_password(admin.password, adminPass):
pass
else:
@ -216,44 +227,40 @@ def deleteWebsite(request):
json_data = json.dumps(data_ret)
return HttpResponse(json_data)
website = Websites.objects.get(domain=websiteName)
website = Websites.objects.get(domain=data['websiteName'])
websiteOwner = website.admin
if admin.websites_set.all().count() == 0:
websiteOwner.delete()
try:
if admin.websites_set.all().count() == 0:
websiteOwner.delete()
except:
pass
## Deleting master domain
numberOfWebsites = str(Websites.objects.count() + ChildDomains.objects.count())
execPath = "sudo python " + virtualHostUtilities.cyberPanel + "/plogical/virtualHostUtilities.py"
execPath = execPath + " deleteVirtualHostConfigurations --virtualHostName " + websiteName + \
" --numberOfSites " + numberOfWebsites
subprocess.check_output(shlex.split(execPath))
data_ret = {'websiteDeleteStatus': 1, 'error_message': "None"}
json_data = json.dumps(data_ret)
return HttpResponse(json_data)
wm = WebsiteManager()
return wm.submitWebsiteDeletion(admin.pk, data)
except BaseException, msg:
data_ret = {'websiteDeleteStatus': 0, 'error_message': str(msg)}
json_data = json.dumps(data_ret)
return HttpResponse(json_data)
@csrf_exempt
def submitWebsiteStatus(request):
try:
if request.method == 'POST':
data = json.loads(request.body)
websiteName = data['websiteName']
state = data['state']
adminUser = data['adminUser']
adminPass = data['adminPass']
admin = Administrator.objects.get(userName=adminUser)
if admin.api == 0:
data_ret = {"websiteStatus": 0, 'error_message': "API Access Disabled."}
json_data = json.dumps(data_ret)
return HttpResponse(json_data)
if hashPassword.check_password(admin.password, adminPass):
pass
else:
@ -262,50 +269,39 @@ def submitWebsiteStatus(request):
json_data = json.dumps(data_ret)
return HttpResponse(json_data)
website = Websites.objects.get(domain=websiteName)
if state == "Suspend":
virtualHostUtilities.suspendVirtualHost(websiteName)
installUtilities.reStartLiteSpeed()
website.state = 0
else:
virtualHostUtilities.UnsuspendVirtualHost(websiteName)
installUtilities.reStartLiteSpeed()
website.state = 1
website.save()
data_ret = {'websiteStatus': 1, 'error_message': "None"}
json_data = json.dumps(data_ret)
return HttpResponse(json_data)
wm = WebsiteManager()
return wm.submitWebsiteStatus(admin.pk, json.loads(request.body))
except BaseException, msg:
data_ret = {'websiteStatus': 0, 'error_message': str(msg)}
json_data = json.dumps(data_ret)
return HttpResponse(json_data)
@csrf_exempt
def loginAPI(request):
try:
if request.method == "POST":
username = request.POST['username']
password = request.POST['password']
username = request.POST['username']
password = request.POST['password']
admin = Administrator.objects.get(userName=username)
admin = Administrator.objects.get(userName=username)
if hashPassword.check_password(admin.password, password):
request.session['userID'] = admin.pk
return redirect(renderBase)
else:
return HttpResponse("Invalid Credentials.")
if admin.api == 0:
data_ret = {"userID": 0, 'error_message': "API Access Disabled."}
json_data = json.dumps(data_ret)
return HttpResponse(json_data)
if hashPassword.check_password(admin.password, password):
request.session['userID'] = admin.pk
return redirect(renderBase)
else:
return HttpResponse("Invalid Credentials.")
except BaseException, msg:
data = {'userID': 0, 'loginStatus': 0, 'error_message': str(msg)}
json_data = json.dumps(data)
return HttpResponse(json_data)
@csrf_exempt
def fetchSSHkey(request):
try:
if request.method == "POST":
@ -315,13 +311,19 @@ def fetchSSHkey(request):
admin = Administrator.objects.get(userName=username)
if admin.api == 0:
data_ret = {"status": 0, 'error_message': "API Access Disabled."}
json_data = json.dumps(data_ret)
return HttpResponse(json_data)
if hashPassword.check_password(admin.password, password):
pubKey = os.path.join("/root",".ssh",'cyberpanel.pub')
execPath = "sudo cat " + pubKey
data = subprocess.check_output(shlex.split(execPath))
execPath = "cat " + pubKey
data = ProcessUtilities.outputExecutioner(execPath)
data_ret = {
'status': 1,
'pubKeyStatus': 1,
'error_message': "None",
'pubKey':data
@ -330,6 +332,7 @@ def fetchSSHkey(request):
return HttpResponse(json_data)
else:
data_ret = {
'status' : 0,
'pubKeyStatus': 0,
'error_message': "Could not authorize access to API."
}
@ -337,10 +340,11 @@ def fetchSSHkey(request):
return HttpResponse(json_data)
except BaseException, msg:
data = {'pubKeyStatus': 0,'error_message': str(msg)}
data = {'status' : 0, 'pubKeyStatus': 0,'error_message': str(msg)}
json_data = json.dumps(data)
return HttpResponse(json_data)
@csrf_exempt
def remoteTransfer(request):
try:
if request.method == "POST":
@ -348,11 +352,18 @@ def remoteTransfer(request):
data = json.loads(request.body)
username = data['username']
password = data['password']
ipAddress = data['ipAddress']
accountsToTransfer = data['accountsToTransfer']
admin = Administrator.objects.get(userName=username)
if admin.api == 0:
data_ret = {"transferStatus": 0, 'error_message': "API Access Disabled."}
json_data = json.dumps(data_ret)
return HttpResponse(json_data)
ipAddress = data['ipAddress']
accountsToTransfer = data['accountsToTransfer']
if hashPassword.check_password(admin.password, password):
dir = str(randint(1000, 9999))
@ -368,9 +379,9 @@ def remoteTransfer(request):
## Accounts to transfer is a path to file, containing accounts.
execPath = "sudo python " + virtualHostUtilities.cyberPanel + "/plogical/remoteTransferUtilities.py"
execPath = "/usr/local/CyberCP/bin/python2 " + virtualHostUtilities.cyberPanel + "/plogical/remoteTransferUtilities.py"
execPath = execPath + " remoteTransfer --ipAddress " + ipAddress + " --dir " + dir + " --accountsToTransfer " + path
subprocess.Popen(shlex.split(execPath))
ProcessUtilities.popenExecutioner(execPath)
return HttpResponse(json.dumps({"transferStatus": 1, "dir": dir}))
@ -385,6 +396,7 @@ def remoteTransfer(request):
json_data = json.dumps(data)
return HttpResponse(json_data)
@csrf_exempt
def fetchAccountsFromRemoteServer(request):
try:
if request.method == "POST":
@ -393,6 +405,12 @@ def fetchAccountsFromRemoteServer(request):
password = data['password']
admin = Administrator.objects.get(userName=username)
if admin.api == 0:
data_ret = {"fetchStatus": 0, 'error_message': "API Access Disabled."}
json_data = json.dumps(data_ret)
return HttpResponse(json_data)
if hashPassword.check_password(admin.password, password):
records = Websites.objects.all()
@ -428,7 +446,7 @@ def fetchAccountsFromRemoteServer(request):
json_data = json.dumps(data)
return HttpResponse(json_data)
@csrf_exempt
def FetchRemoteTransferStatus(request):
try:
if request.method == "POST":
@ -436,13 +454,20 @@ def FetchRemoteTransferStatus(request):
username = data['username']
password = data['password']
admin = Administrator.objects.get(userName=username)
if admin.api == 0:
data_ret = {"fetchStatus": 0, 'error_message': "API Access Disabled."}
json_data = json.dumps(data_ret)
return HttpResponse(json_data)
dir = "/home/backup/transfer-"+str(data['dir'])+"/backup_log"
try:
command = "sudo cat "+ dir
status = subprocess.check_output(shlex.split(command))
command = "cat "+ dir
status = ProcessUtilities.outputExecutioner(command)
admin = Administrator.objects.get(userName=username)
if hashPassword.check_password(admin.password, password):
final_json = json.dumps({'fetchStatus': 1, 'error_message': "None", "status": status})
@ -462,28 +487,37 @@ def FetchRemoteTransferStatus(request):
json_data = json.dumps(data)
return HttpResponse(json_data)
@csrf_exempt
def cancelRemoteTransfer(request):
try:
if request.method == "POST":
data = json.loads(request.body)
username = data['username']
password = data['password']
dir = "/home/backup/transfer-"+str(data['dir'])
admin = Administrator.objects.get(userName=username)
if admin.api == 0:
data_ret = {"cancelStatus": 0, 'error_message': "API Access Disabled."}
json_data = json.dumps(data_ret)
return HttpResponse(json_data)
dir = "/home/backup/transfer-"+str(data['dir'])
if hashPassword.check_password(admin.password, password):
path = dir + "/pid"
command = "sudo cat " + path
pid = subprocess.check_output(shlex.split(command))
command = "cat " + path
pid = ProcessUtilities.outputExecutioner(command)
command = "sudo kill -KILL " + pid
subprocess.call(shlex.split(command))
command = "kill -KILL " + pid
ProcessUtilities.executioner(command)
command = "sudo rm -rf " + dir
subprocess.call(shlex.split(command))
command = "rm -rf " + dir
ProcessUtilities.executioner(command)
data = {'cancelStatus': 1, 'error_message': "None"}
json_data = json.dumps(data)
@ -500,6 +534,7 @@ def cancelRemoteTransfer(request):
json_data = json.dumps(data)
return HttpResponse(json_data)
@csrf_exempt
def cyberPanelVersion(request):
try:
if request.method == 'POST':
@ -512,6 +547,11 @@ def cyberPanelVersion(request):
admin = Administrator.objects.get(userName=adminUser)
if admin.api == 0:
data_ret = {"getVersion": 0, 'error_message': "API Access Disabled."}
json_data = json.dumps(data_ret)
return HttpResponse(json_data)
if hashPassword.check_password(admin.password, adminPass):
Version = version.objects.get(pk=1)
@ -541,105 +581,15 @@ def cyberPanelVersion(request):
json_data = json.dumps(data_ret)
return HttpResponse(json_data)
def putSSHkey(request):
try:
if request.method == 'POST':
data = json.loads(request.body)
adminUser = data['username']
adminPass = data['password']
pubKey = data['putSSHKey']
admin = Administrator.objects.get(userName=adminUser)
if hashPassword.check_password(admin.password, adminPass):
keyPath = "/home/cyberpanel/.ssh"
if not os.path.exists(keyPath):
os.makedirs(keyPath)
## writeKey
authorized_keys = keyPath+"/authorized_keys"
presenseCheck = 0
try:
data = open(authorized_keys, "r").readlines()
for items in data:
if items.find(pubKey) > -1:
presenseCheck = 1
except:
pass
if presenseCheck == 0:
writeToFile = open(authorized_keys, 'a')
writeToFile.writelines("#Added by CyberPanel\n")
writeToFile.writelines("\n")
writeToFile.writelines(pubKey)
writeToFile.writelines("\n")
writeToFile.close()
##
command = "sudo chmod g-w /home/cyberpanel"
cmd = shlex.split(command)
res = subprocess.call(cmd)
os.chmod(keyPath,0700)
os.chmod(authorized_keys, 0600)
data_ret = {"putSSHKey": 1,
'error_message': "None",}
json_data = json.dumps(data_ret)
return HttpResponse(json_data)
else:
data_ret = {"putSSHKey": 0,
'error_message': "Could not authorize access to API"}
json_data = json.dumps(data_ret)
return HttpResponse(json_data)
except BaseException, msg:
data_ret = {"putSSHKey": 0,
'error_message': str(msg)}
json_data = json.dumps(data_ret)
return HttpResponse(json_data)
def changeAdminPassword(request):
@csrf_exempt
def runAWSBackups(request):
try:
data = json.loads(request.body)
adminPass = data['password']
randomFile = data['randomFile']
if os.path.exists(randomFile):
os.remove(randomFile)
admin = Administrator.objects.get(userName="admin")
admin.password = hashPassword.hash_password(adminPass)
admin.save()
data_ret = {"changed": 1,
'error_message': "None"}
json_data = json.dumps(data_ret)
return HttpResponse(json_data)
else:
data_ret = {"changed": 0,
'error_message': "Failed to authorize access to change password!"}
json_data = json.dumps(data_ret)
return HttpResponse(json_data)
s3 = S3Backups(request, None, 'runAWSBackups')
s3.start()
except BaseException, msg:
data_ret = {"changed": 0,
'error_message': "Failed to authorize access to change password!"}
json_data = json.dumps(data_ret)
return HttpResponse(json_data)
logging.writeToFile(str(msg) + ' [API.runAWSBackups]')

1171
backup/backupManager.py Normal file

File diff suppressed because it is too large Load Diff

104
backup/pluginManager.py Normal file
View File

@ -0,0 +1,104 @@
from signals import *
from plogical.pluginManagerGlobal import pluginManagerGlobal
class pluginManager:
@staticmethod
def preBackupSite(request):
return pluginManagerGlobal.globalPlug(request, preBackupSite)
@staticmethod
def postBackupSite(request, response):
return pluginManagerGlobal.globalPlug(request, postBackupSite, response)
@staticmethod
def preRestoreSite(request):
return pluginManagerGlobal.globalPlug(request, preRestoreSite)
@staticmethod
def postRestoreSite(request, response):
return pluginManagerGlobal.globalPlug(request, postRestoreSite, response)
@staticmethod
def preSubmitBackupCreation(request):
return pluginManagerGlobal.globalPlug(request, preSubmitBackupCreation)
@staticmethod
def preBackupStatus(request):
return pluginManagerGlobal.globalPlug(request, preBackupStatus)
@staticmethod
def postBackupStatus(request, response):
return pluginManagerGlobal.globalPlug(request, postBackupStatus, response)
@staticmethod
def preDeleteBackup(request):
return pluginManagerGlobal.globalPlug(request, preDeleteBackup)
@staticmethod
def postDeleteBackup(request, response):
return pluginManagerGlobal.globalPlug(request, postDeleteBackup, response)
@staticmethod
def preSubmitRestore(request):
return pluginManagerGlobal.globalPlug(request, preSubmitRestore)
@staticmethod
def preSubmitDestinationCreation(request):
return pluginManagerGlobal.globalPlug(request, preSubmitDestinationCreation)
@staticmethod
def postSubmitDestinationCreation(request, response):
return pluginManagerGlobal.globalPlug(request, postSubmitDestinationCreation, response)
@staticmethod
def preDeleteDestination(request):
return pluginManagerGlobal.globalPlug(request, preDeleteDestination)
@staticmethod
def postDeleteDestination(request, response):
return pluginManagerGlobal.globalPlug(request, postDeleteDestination, response)
@staticmethod
def preSubmitBackupSchedule(request):
return pluginManagerGlobal.globalPlug(request, preSubmitBackupSchedule)
@staticmethod
def postSubmitBackupSchedule(request, response):
return pluginManagerGlobal.globalPlug(request, postSubmitBackupSchedule, response)
@staticmethod
def preScheduleDelete(request):
return pluginManagerGlobal.globalPlug(request, preScheduleDelete)
@staticmethod
def postScheduleDelete(request, response):
return pluginManagerGlobal.globalPlug(request, postScheduleDelete, response)
@staticmethod
def preSubmitRemoteBackups(request):
return pluginManagerGlobal.globalPlug(request, preSubmitRemoteBackups)
@staticmethod
def postSubmitRemoteBackups(request, response):
return pluginManagerGlobal.globalPlug(request, postSubmitRemoteBackups, response)
@staticmethod
def preStarRemoteTransfer(request):
return pluginManagerGlobal.globalPlug(request, preStarRemoteTransfer)
@staticmethod
def postStarRemoteTransfer(request, response):
return pluginManagerGlobal.globalPlug(request, postStarRemoteTransfer, response)
@staticmethod
def preRemoteBackupRestore(request):
return pluginManagerGlobal.globalPlug(request, preRemoteBackupRestore)
@staticmethod
def postRemoteBackupRestore(request, response):
return pluginManagerGlobal.globalPlug(request, postRemoteBackupRestore, response)
@staticmethod
def postDeleteBackup(request, response):
return pluginManagerGlobal.globalPlug(request, postRemoteBackupRestore, response)

75
backup/signals.py Normal file
View File

@ -0,0 +1,75 @@
# The world is a prison for the believer.
from django.dispatch import Signal
## This event is fired before CyberPanel core load template for create backup page.
preBackupSite = Signal(providing_args=["request"])
## This event is fired after CyberPanel core load template for create backup page.
postBackupSite = Signal(providing_args=["request", "response"])
## This event is fired before CyberPanel core load template for restore backup page.
preRestoreSite = Signal(providing_args=["request"])
## This event is fired after CyberPanel core load template for restore backup page.
postRestoreSite = Signal(providing_args=["request", "response"])
## This event is fired before CyberPanel core start creating backup of a website
preSubmitBackupCreation = Signal(providing_args=["request"])
## This event is fired before CyberPanel core starts to load status of backup started earlier througb submitBackupCreation
preBackupStatus = Signal(providing_args=["request"])
## This event is fired after CyberPanel core has loaded backup status
postBackupStatus = Signal(providing_args=["request", "response"])
## This event is fired before CyberPanel core start deletion of a backup
preDeleteBackup = Signal(providing_args=["request"])
## This event is fired after CyberPanel core finished the backup deletion
postDeleteBackup = Signal(providing_args=["request", "response"])
## This event is fired before CyberPanel core start restoring a backup.
preSubmitRestore = Signal(providing_args=["request"])
## This event is fired before CyberPanel core starts to add a remote backup destination
preSubmitDestinationCreation = Signal(providing_args=["request"])
## This event is fired after CyberPanel core is finished adding remote backup destination
postSubmitDestinationCreation = Signal(providing_args=["request", "response"])
## This event is fired before CyberPanel core starts to delete a backup destination
preDeleteDestination = Signal(providing_args=["request"])
## This event is fired after CyberPanel core finished deleting a backup destination
postDeleteDestination = Signal(providing_args=["request", "response"])
## This event is fired before CyberPanel core start adding a backup schedule
preSubmitBackupSchedule = Signal(providing_args=["request"])
## This event is fired after CyberPanel core finished adding a backup schedule
postSubmitBackupSchedule = Signal(providing_args=["request", "response"])
## This event is fired before CyberPanel core start the deletion of backup schedule
preScheduleDelete = Signal(providing_args=["request"])
## This event is fired after CyberPanel core finished the deletion of backup schedule
postScheduleDelete = Signal(providing_args=["request", "response"])
## This event is fired before CyberPanel core star the remote backup process
preSubmitRemoteBackups = Signal(providing_args=["request"])
## This event is fired after CyberPanel core finished remote backup process
postSubmitRemoteBackups = Signal(providing_args=["request", "response"])
## This event is fired before CyberPanel core star the remote backup process
preStarRemoteTransfer = Signal(providing_args=["request"])
## This event is fired after CyberPanel core finished remote backup process
postStarRemoteTransfer = Signal(providing_args=["request", "response"])
## This event is fired before CyberPanel core start restore of remote backups
preRemoteBackupRestore = Signal(providing_args=["request"])
## This event is fired after CyberPanel core finished restoring remote backups in local server
postRemoteBackupRestore = Signal(providing_args=["request", "response"])

File diff suppressed because it is too large Load Diff

View File

@ -63,8 +63,7 @@
<div class="form-group">
<label class="col-sm-3 control-label"></label>
<div class="col-sm-4">
<div class="col-sm-12">
<div ng-hide="connectionFailed" class="alert alert-danger">
<p>{% trans "Connection to" %} {$ IPAddress $} {% trans "failed. Please delete and re-add. " %} {$ errorMessage $} </p>
</div>

View File

@ -3,121 +3,134 @@
{% block title %}{% trans "Schedule Back up - CyberPanel" %} {% endblock %}
{% block content %}
{% load static %}
{% get_current_language as LANGUAGE_CODE %}
<!-- Current language: {{ LANGUAGE_CODE }} -->
<div class="container">
<div id="page-title">
<h2>{% trans "Schedule Back up" %} - <a target="_blank" href="http://go.cyberpanel.net/remote-backup" style="height: 23px;line-height: 21px;" class="btn btn-border btn-alt border-red btn-link font-red" title=""><span>{% trans "Remote Backups" %}</span></a></h2>
<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 class="panel-body">
<h3 class="title-hero">
{% trans "Schedule Back up" %} <img ng-hide="scheduleBackupLoading" src="{% static 'images/loading.gif' %}">
</h3>
<div class="example-box-wrapper">
<form action="/" class="form-horizontal bordered-row">
<div class="form-group">
<label class="col-sm-3 control-label">{% trans "Select Destination" %}</label>
<div class="col-sm-6">
<select ng-change="scheduleFreqView()" ng-model="backupDest" class="form-control">
{% for items in destinations %}
<option>{{ items }}</option>
{% endfor %}
</select>
</div>
</div>
<div ng-hide="scheduleFreq" class="form-group">
<label class="col-sm-3 control-label">{% trans "Select Frequency" %}</label>
<div class="col-sm-6">
<select ng-change="scheduleBtnView()" ng-model="backupFreq" class="form-control">
<option>Daily</option>
<option>Weekly</option>
</select>
</div>
</div>
<div ng-hide="scheduleBtn" class="form-group">
<label class="col-sm-3 control-label"></label>
<div class="col-sm-4">
<button type="button" ng-click="addSchedule()" class="btn btn-primary btn-lg btn-block">{% trans "Add Destination" %}</button>
</div>
</div>
<!------ List of Destinations --------------->
<div 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>
</div>
</div>
<div class="form-group">
<div class="col-sm-12">
<table class="table">
<thead>
<tr>
<th>{% trans "ID" %}</th>
<th>{% trans "Destination" %}</th>
<th>{% trans "Frequency" %}</th>
<th>{% trans "Delete" %}</th>
</tr>
</thead>
<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.frequency"></td>
<td ng-click="delSchedule(record.destLoc,record.frequency)"><img src="{% static 'images/delete.png' %}"></td>
</tr>
</tbody>
</table>
</div>
</div>
<!------ List of records --------------->
</form>
{% load static %}
{% get_current_language as LANGUAGE_CODE %}
<!-- Current language: {{ LANGUAGE_CODE }} -->
<div class="container">
<div id="page-title">
<h2>{% trans "Schedule Back up" %} - <a target="_blank" href="http://go.cyberpanel.net/remote-backup"
style="height: 23px;line-height: 21px;"
class="btn btn-border btn-alt border-red btn-link font-red"
title=""><span>{% trans "Remote Backups" %}</span></a></h2>
<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 class="panel-body">
<h3 class="title-hero">
{% trans "Schedule Back up" %} <img ng-hide="scheduleBackupLoading"
src="{% static 'images/loading.gif' %}">
</h3>
<div class="example-box-wrapper">
<form action="/" class="form-horizontal bordered-row">
<div class="form-group">
<label class="col-sm-3 control-label">{% trans "Select Destination" %}</label>
<div class="col-sm-6">
<select ng-change="scheduleFreqView()" ng-model="backupDest" class="form-control">
{% for items in destinations %}
<option>{{ items }}</option>
{% endfor %}
</select>
</div>
</div>
<div ng-hide="scheduleFreq" class="form-group">
<label class="col-sm-3 control-label">{% trans "Select Frequency" %}</label>
<div class="col-sm-6">
<select ng-change="scheduleBtnView()" ng-model="backupFreq" class="form-control">
<option>Daily</option>
<option>Weekly</option>
</select>
</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>
</div>
<div ng-hide="scheduleBtn" class="form-group">
<label class="col-sm-3 control-label"></label>
<div class="col-sm-4">
<button type="button" ng-click="addSchedule()"
class="btn btn-primary btn-lg btn-block">{% trans "Add Destination" %}</button>
</div>
</div>
<!------ List of Destinations --------------->
<div 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>
</div>
</div>
<div class="form-group">
<div class="col-sm-12">
<table class="table">
<thead>
<tr>
<th>{% trans "ID" %}</th>
<th>{% trans "Destination" %}</th>
<th>{% trans "Frequency" %}</th>
<th>{% trans "Delete" %}</th>
</tr>
</thead>
<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.frequency"></td>
<td ng-click="delSchedule(record.destLoc,record.frequency)"><img
src="{% static 'images/delete.png' %}"></td>
</tr>
</tbody>
</table>
</div>
</div>
<!------ List of records --------------->
</form>
</div>
</div>
</div>
</div>
</div>
</div>
{% endblock %}

View File

@ -13,60 +13,94 @@
<h2>{% trans "Back up" %}</h2>
<p>{% trans "Back up and restore sites." %}</p>
</div>
<div class="panel">
<div class="panel col-md-11">
<div class="panel-body">
<h3 class="title-hero">
<h3 class="content-box-header">
{% trans "Available Functions" %}
</h3>
<div class="example-box-wrapper">
{% if viewStatus == 0 %}
<div class="row">
<div class="row">
<div class="col-md-6">
<a href="{% url 'backupSite' %}" title="{% trans 'Back up Site' %}" class="tile-box tile-box-shortcut btn-primary">
<div class="tile-header">
{% trans "Back up" %}
</div>
<div class="tile-content-wrapper">
<i class="glyph-icon icon-dashboard"></i>
</div>
</a>
</div>
{% if createBackup or admin %}
</div>
<div class="col-md-3 btn-min-width">
<a href="{% url 'backupSite' %}" title="{% trans 'Back up Site' %}" class="tile-box tile-box-shortcut btn-primary">
<div class="tile-header">
{% trans "Back up" %}
</div>
<div class="tile-content-wrapper">
<i class="fa fa-clone"></i>
</div>
</a>
</div>
{% else %}
{% endif %}
<div class="row">
<div class="col-md-6">
<a href="{% url 'backupSite' %}" title="{% trans 'Back up Site' %}" class="tile-box tile-box-shortcut btn-primary">
<div class="tile-header">
{% trans "Back up" %}
</div>
<div class="tile-content-wrapper">
<i class="glyph-icon icon-dashboard"></i>
</div>
</a>
</div>
{% if restoreBackup or admin %}
<div class="col-md-6">
<a href="{% url 'restoreSite' %}" title="{% trans 'Restore Back up' %}" class="tile-box tile-box-shortcut btn-primary">
<div class="tile-header">
{% trans "Restore" %}
</div>
<div class="tile-content-wrapper">
<i class="glyph-icon icon-dashboard"></i>
</div>
</a>
</div>
<div class="col-md-3 btn-min-width">
<a href="{% url 'restoreSite' %}" title="{% trans 'Restore Back up' %}" class="tile-box tile-box-shortcut btn-primary">
<div class="tile-header">
{% trans "Restore" %}
</div>
<div class="tile-content-wrapper">
<i class="fa fa-undo"></i>
</div>
</a>
</div>
{% endif %}
{% if addDeleteDestinations or admin %}
<div class="col-md-3 btn-min-width">
<a href="{% url 'backupDestinations' %}" title="{% trans 'Add/Delete Destinations' %}" class="tile-box tile-box-shortcut btn-primary">
<div class="tile-header">
{% trans "Add/Delete Destinations" %}
</div>
<div class="tile-content-wrapper">
<i class="fa fa-map-pin"></i>
</div>
</a>
</div>
{% endif %}
{% if scheDuleBackups or admin %}
<div class="col-md-3 btn-min-width">
<a href="{% url 'scheduleBackup' %}" title="{% trans 'Schedule Back up' %}" class="tile-box tile-box-shortcut btn-primary">
<div class="tile-header">
{% trans "Schedule Back up" %}
</div>
<div class="tile-content-wrapper">
<i class="fa fa-refresh"></i>
</div>
</a>
</div>
{% endif %}
{% if remoteBackups or admin %}
<div class="col-md-3 btn-min-width">
<a href="{% url 'remoteBackups' %}" title="{% trans 'Remote Back ups' %}" class="tile-box tile-box-shortcut btn-primary">
<div class="tile-header">
{% trans "Remote Back ups" %}
</div>
<div class="tile-content-wrapper">
<i class="fa fa-cloud-upload"></i>
</div>
</a>
</div>
{% endif %}
</div>
{% endif %}
</div>
</div>
</div>
@ -74,4 +108,4 @@
</div>
{% endblock %}
{% endblock %}

View File

@ -46,6 +46,8 @@ urlpatterns = [
url(r'^cancelRemoteBackup', views.cancelRemoteBackup, name='cancelRemoteBackup'),
url(r'^localInitiate$', views.localInitiate, name='localInitiate'),

File diff suppressed because it is too large Load Diff

View File

View File

View File

0
baseTemplate/static/baseTemplate/assets/bootstrap/css/bootstrap.css vendored Executable file → Normal file
View File

View File

View File

Before

Width:  |  Height:  |  Size: 106 KiB

After

Width:  |  Height:  |  Size: 106 KiB

0
baseTemplate/static/baseTemplate/assets/bootstrap/js/bootstrap.js vendored Executable file → Normal file
View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

Before

Width:  |  Height:  |  Size: 280 KiB

After

Width:  |  Height:  |  Size: 280 KiB

View File

View File

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 33 KiB

View File

View File

View File

View File

Before

Width:  |  Height:  |  Size: 5.6 KiB

After

Width:  |  Height:  |  Size: 5.6 KiB

View File

View File

Some files were not shown because too many files have changed in this diff Show More