mirror of
https://github.com/usmannasir/cyberpanel.git
synced 2026-05-07 03:25:55 +02:00
push changes
This commit is contained in:
0
containerization/__init__.py
Normal file
0
containerization/__init__.py
Normal file
6
containerization/admin.py
Normal file
6
containerization/admin.py
Normal file
@@ -0,0 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.contrib import admin
|
||||
|
||||
# Register your models here.
|
||||
8
containerization/apps.py
Normal file
8
containerization/apps.py
Normal file
@@ -0,0 +1,8 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class ContainerizationConfig(AppConfig):
|
||||
name = 'containerization'
|
||||
125
containerization/container.py
Normal file
125
containerization/container.py
Normal file
@@ -0,0 +1,125 @@
|
||||
#!/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 Container:
|
||||
packages = ['talksho']
|
||||
users = ['5001']
|
||||
|
||||
@staticmethod
|
||||
def listAll():
|
||||
try:
|
||||
counter = 0
|
||||
length = len(Container.users)
|
||||
for items in Container.users:
|
||||
if (counter + 1) == length:
|
||||
print items + ' ' + Container.packages[counter]
|
||||
else:
|
||||
print items + ' ' + Container.packages[counter] + ' '
|
||||
counter = counter + 1
|
||||
|
||||
except BaseException, msg:
|
||||
logging.CyberCPLogFileWriter.writeToFile(str(msg))
|
||||
|
||||
@staticmethod
|
||||
def listPackages():
|
||||
try:
|
||||
counter = 0
|
||||
length = len(Container.users)
|
||||
for items in Container.packages:
|
||||
if (counter + 1) == length:
|
||||
print items
|
||||
else:
|
||||
print items + '\n'
|
||||
counter = counter + 1
|
||||
|
||||
except BaseException, msg:
|
||||
logging.CyberCPLogFileWriter.writeToFile(str(msg))
|
||||
|
||||
@staticmethod
|
||||
def userIDPackage(user):
|
||||
try:
|
||||
counter = 0
|
||||
for items in Container.users:
|
||||
if items == user:
|
||||
print Container.packages[counter]
|
||||
return
|
||||
counter = counter + 1
|
||||
except BaseException, msg:
|
||||
logging.CyberCPLogFileWriter.writeToFile(str(msg))
|
||||
|
||||
@staticmethod
|
||||
def packageForUser(package):
|
||||
try:
|
||||
counter = 0
|
||||
for items in Container.packages:
|
||||
if items == package:
|
||||
print Container.users[counter]
|
||||
return
|
||||
counter = counter + 1
|
||||
except BaseException, msg:
|
||||
logging.CyberCPLogFileWriter.writeToFile(str(msg))
|
||||
|
||||
@staticmethod
|
||||
def submitContainerInstall():
|
||||
try:
|
||||
|
||||
mailUtilities.checkHome()
|
||||
|
||||
statusFile = open(ServerStatusUtil.lswsInstallStatusPath, 'w')
|
||||
|
||||
logging.CyberCPLogFileWriter.statusWriter(ServerStatusUtil.lswsInstallStatusPath,
|
||||
"Starting Packages Installation..\n", 1)
|
||||
|
||||
command = 'sudo yum install -y libcgroup-tools'
|
||||
ServerStatusUtil.executioner(command, statusFile)
|
||||
|
||||
command = 'sudo systemctl enable cgconfig'
|
||||
ServerStatusUtil.executioner(command, statusFile)
|
||||
|
||||
command = 'sudo systemctl enable cgred'
|
||||
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 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']:
|
||||
Container.userIDPackage(args['userid'])
|
||||
elif args['package']:
|
||||
Container.packageForUser(args['package'])
|
||||
elif args['list_all']:
|
||||
Container.listAll()
|
||||
elif args['list_packages']:
|
||||
Container.listPackages()
|
||||
elif args['list_packages']:
|
||||
Container.listPackages()
|
||||
elif args["function"] == "submitContainerInstall":
|
||||
Container.submitContainerInstall()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
179
containerization/containerManager.py
Normal file
179
containerization/containerManager.py
Normal file
@@ -0,0 +1,179 @@
|
||||
from django.shortcuts import render
|
||||
from plogical.processUtilities import ProcessUtilities
|
||||
import threading as multi
|
||||
from plogical.acl import ACLManager
|
||||
import plogical.CyberCPLogFileWriter as logging
|
||||
from serverStatus.serverStatusUtil import ServerStatusUtil
|
||||
import os, stat
|
||||
|
||||
|
||||
class ContainerManager(multi.Thread):
|
||||
defaultConf = """group {groupName}{
|
||||
cpu {
|
||||
cpu.cfs_quota_us = {cfs_quota_us};
|
||||
cpu.cfs_period_us = {cfs_period_us};
|
||||
}
|
||||
memory {
|
||||
memory.limit_in_bytes = {memory}m;
|
||||
}
|
||||
blkio {
|
||||
blkio.throttle.read_bps_device = "{major}:{minor} {io}";
|
||||
blkio.throttle.write_bps_device = "{major}:{minor} {io}";
|
||||
blkio.throttle.read_iops_device = "{major}:{minor} {iops}";
|
||||
blkio.throttle.write_iops_device = "{major}:{minor} {iops}";
|
||||
}
|
||||
net_cls
|
||||
{
|
||||
net_cls.classid = 0x10{net_cls};
|
||||
}
|
||||
}"""
|
||||
|
||||
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 == 'submitContainerInstall':
|
||||
self.submitContainerInstall()
|
||||
elif self.function == 'addTrafficController':
|
||||
self.addTrafficController()
|
||||
elif self.function == 'removeLimits':
|
||||
self.removeLimits()
|
||||
except BaseException, msg:
|
||||
logging.CyberCPLogFileWriter.writeToFile(str(msg) + ' [ContainerManager.run]')
|
||||
|
||||
@staticmethod
|
||||
def fetchHexValue(count):
|
||||
hexValue = format(count, '02x')
|
||||
|
||||
if len(hexValue) == 1:
|
||||
return '000' + hexValue
|
||||
elif len(hexValue) == 2:
|
||||
return '00' + hexValue
|
||||
elif len(hexValue) == 3:
|
||||
return '0' + hexValue
|
||||
elif len(hexValue) == 3:
|
||||
return hexValue
|
||||
|
||||
@staticmethod
|
||||
def prepConf(groupName, cfs_quota_us, cfs_period_us, memory, io, iops, net_cls):
|
||||
try:
|
||||
dev = os.stat('/')[stat.ST_DEV]
|
||||
major = str(os.major(dev))
|
||||
minor = str(0)
|
||||
finalIO = str(int(io) * 1024 * 1024)
|
||||
|
||||
ioConf = ContainerManager.defaultConf.replace('{groupName}', groupName)
|
||||
ioConf = ioConf.replace('{cfs_quota_us}', cfs_quota_us)
|
||||
ioConf = ioConf.replace('{cfs_period_us}', cfs_period_us)
|
||||
ioConf = ioConf.replace('{memory}', memory)
|
||||
ioConf = ioConf.replace('{major}', major)
|
||||
ioConf = ioConf.replace('{minor}', minor)
|
||||
ioConf = ioConf.replace('{io}', finalIO)
|
||||
ioConf = ioConf.replace('{iops}', str(iops))
|
||||
ioConf = ioConf.replace('{net_cls}', str(net_cls))
|
||||
|
||||
return ioConf
|
||||
except BaseException, msg:
|
||||
logging.CyberCPLogFileWriter.writeToFile(str(msg))
|
||||
return 0
|
||||
|
||||
def renderC(self):
|
||||
|
||||
userID = self.request.session['userID']
|
||||
currentACL = ACLManager.loadedACL(userID)
|
||||
|
||||
if currentACL['admin'] == 1:
|
||||
pass
|
||||
else:
|
||||
return ACLManager.loadError()
|
||||
|
||||
data = {}
|
||||
data['OLS'] = 0
|
||||
data['notInstalled'] = 0
|
||||
|
||||
if ProcessUtilities.decideServer() == ProcessUtilities.OLS:
|
||||
data['OLS'] = 1
|
||||
data['notInstalled'] = 0
|
||||
return render(self.request, 'containerization/notAvailable.html', data)
|
||||
elif not ProcessUtilities.containerCheck():
|
||||
data['OLS'] = 0
|
||||
data['notInstalled'] = 1
|
||||
return render(self.request, 'containerization/notAvailable.html', data)
|
||||
else:
|
||||
if self.data == None:
|
||||
self.data = {}
|
||||
self.data['OLS'] = 0
|
||||
self.data['notInstalled'] = 0
|
||||
return render(self.request, self.templateName, self.data)
|
||||
|
||||
def submitContainerInstall(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/containerization/container.py"
|
||||
execPath = execPath + " --function submitContainerInstall"
|
||||
ProcessUtilities.outputExecutioner(execPath)
|
||||
|
||||
except BaseException, msg:
|
||||
logging.CyberCPLogFileWriter.statusWriter(ServerStatusUtil.lswsInstallStatusPath, str(msg) + ' [404].', 1)
|
||||
|
||||
def restartServices(self):
|
||||
command = 'sudo systemctl restart cgconfig'
|
||||
ProcessUtilities.executioner(command)
|
||||
|
||||
command = 'sudo systemctl restart cgred'
|
||||
ProcessUtilities.executioner(command)
|
||||
|
||||
def addTrafficController(self):
|
||||
command = 'sudo tc qdisc add dev eth0 root handle 10: htb default 1000'
|
||||
#logging.CyberCPLogFileWriter.writeToFile(command)
|
||||
ProcessUtilities.executioner(command)
|
||||
|
||||
try:
|
||||
command = 'sudo tc class del dev eth0 classid 10:' + str(self.data['classID'])
|
||||
# logging.CyberCPLogFileWriter.writeToFile(command)
|
||||
ProcessUtilities.executioner(command)
|
||||
except:
|
||||
pass
|
||||
|
||||
command = 'sudo tc class add dev eth0 parent 10: classid 10:1000 htb rate 100mbit'
|
||||
#logging.CyberCPLogFileWriter.writeToFile(command)
|
||||
ProcessUtilities.executioner(command)
|
||||
|
||||
command = 'sudo tc class add dev eth0 parent 10: classid 10:' + str(self.data['classID']) + ' htb rate ' + str(self.data['rateLimit'])
|
||||
#logging.CyberCPLogFileWriter.writeToFile(command)
|
||||
ProcessUtilities.executioner(command)
|
||||
|
||||
#if str(self.data['classID']) == '1':
|
||||
# command = 'sudo tc filter add dev eth0 parent 10: protocol ip prio 10 handle 1: cgroup'
|
||||
#else:
|
||||
# command = 'sudo tc filter add dev eth0 parent 10:' + str(
|
||||
# self.data['classID']) + ' protocol ip prio 10 handle 1: cgroup'
|
||||
|
||||
command = 'sudo tc filter add dev eth0 parent 10: protocol ip prio 10 handle 1: cgroup'
|
||||
#logging.CyberCPLogFileWriter.writeToFile(command)
|
||||
ProcessUtilities.executioner(command)
|
||||
|
||||
self.restartServices()
|
||||
|
||||
def removeLimits(self):
|
||||
command = 'sudo tc class del dev eth0 classid 10:' + str(self.data['classID'])
|
||||
#logging.CyberCPLogFileWriter.writeToFile(command)
|
||||
ProcessUtilities.executioner(command)
|
||||
|
||||
self.restartServices()
|
||||
|
||||
0
containerization/migrations/__init__.py
Normal file
0
containerization/migrations/__init__.py
Normal file
16
containerization/models.py
Normal file
16
containerization/models.py
Normal file
@@ -0,0 +1,16 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models
|
||||
from websiteFunctions.models import Websites
|
||||
# Create your models here.
|
||||
|
||||
class ContainerLimits(models.Model):
|
||||
owner = models.ForeignKey(Websites, on_delete=models.CASCADE)
|
||||
cpuPers = models.CharField(max_length=10)
|
||||
IO = models.CharField(max_length=10)
|
||||
IOPS = models.CharField(max_length=10)
|
||||
memory = models.CharField(max_length=10)
|
||||
networkSpeed = models.CharField(max_length=10)
|
||||
networkHexValue = models.CharField(max_length=10)
|
||||
enforce = models.IntegerField(default=0)
|
||||
649
containerization/static/containerization/containerization.js
Normal file
649
containerization/static/containerization/containerization.js
Normal file
@@ -0,0 +1,649 @@
|
||||
app.controller('installContainer', function ($scope, $http, $timeout, $window) {
|
||||
$scope.installDockerStatus = true;
|
||||
$scope.installBoxGen = true;
|
||||
$scope.dockerInstallBTN = false;
|
||||
|
||||
$scope.submitContainerInstall = function () {
|
||||
|
||||
$scope.installDockerStatus = false;
|
||||
$scope.installBoxGen = true;
|
||||
$scope.dockerInstallBTN = true;
|
||||
|
||||
url = "/container/submitContainerInstall";
|
||||
|
||||
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('websiteContainerLimit', 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: "/container/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: "/container/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: "/container/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 () {
|
||||
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);
|
||||
});
|
||||
|
||||
////
|
||||
|
||||
$scope.cyberPanelLoading = true;
|
||||
$scope.limitsInfoBox = true;
|
||||
|
||||
$scope.fetchWebsiteLimits = function () {
|
||||
|
||||
$scope.cyberPanelLoading = false;
|
||||
|
||||
url = "/container/fetchWebsiteLimits";
|
||||
|
||||
var data = {
|
||||
'domain': $("#domain").text()
|
||||
};
|
||||
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.cpuPers = response.data.cpuPers;
|
||||
$scope.IO = response.data.IO;
|
||||
$scope.IOPS = response.data.IOPS;
|
||||
$scope.memory = response.data.memory;
|
||||
$scope.networkSpeed = response.data.networkSpeed;
|
||||
|
||||
if (response.data.enforce === 0) {
|
||||
$scope.limitsInfoBox = false;
|
||||
} else {
|
||||
$scope.limitsInfoBox = true;
|
||||
}
|
||||
|
||||
|
||||
// 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);
|
||||
}
|
||||
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.fetchWebsiteLimits();
|
||||
|
||||
$scope.saveWebsiteLimits = function () {
|
||||
|
||||
$scope.cyberPanelLoading = false;
|
||||
|
||||
url = "/container/saveWebsiteLimits";
|
||||
|
||||
var data = {
|
||||
'domain': $("#domain").text(),
|
||||
'cpuPers': $scope.cpuPers,
|
||||
'IO': $scope.IO,
|
||||
'IOPS': $scope.IOPS,
|
||||
'memory': $scope.memory,
|
||||
'networkSpeed': $scope.networkSpeedBox,
|
||||
'networkHandle': $scope.networkHandle,
|
||||
'enforce': $scope.enforce
|
||||
};
|
||||
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.fetchWebsiteLimits();
|
||||
}
|
||||
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'
|
||||
});
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
});
|
||||
@@ -0,0 +1,87 @@
|
||||
{% extends "baseTemplate/index.html" %}
|
||||
{% load i18n %}
|
||||
{% block title %}{% trans "Limits - 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 "Launch and set limits for the 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="/container/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 %}
|
||||
@@ -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 "CyberPanel Ent is required for Containerization." %}</p>
|
||||
</div>
|
||||
|
||||
{% if OLS %}
|
||||
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
<div class="alert alert-danger">
|
||||
<p>{% trans "Containerization is only available on CyberPanel Ent. " %} <a target="_blank"
|
||||
href="https://cyberpanel.net/docs/switching-from-openlitespeed-to-litespeed-enterprise-webserver/">Click
|
||||
Here</a> {% trans " for conversion details." %}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% elif notInstalled %}
|
||||
|
||||
<div ng-controller="installContainer" 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 "Required packages are 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 class="btn btn-primary" ng-click="submitContainerInstall()">Install Now</button>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
@@ -0,0 +1,186 @@
|
||||
{% extends "baseTemplate/index.html" %}
|
||||
{% load i18n %}
|
||||
{% block title %}{{ domain }}{% trans " limits - CyberPanel" %}{% endblock %}
|
||||
{% block content %}
|
||||
|
||||
{% load static %}
|
||||
{% get_current_language as LANGUAGE_CODE %}
|
||||
<!-- Current language: {{ LANGUAGE_CODE }} -->
|
||||
|
||||
|
||||
<div ng-controller="websiteContainerLimit" class="container">
|
||||
|
||||
<div id="page-title">
|
||||
<h2 id="domainNamePage">{% trans "Limits/Usage" %}</h2> <img ng-hide="cyberPanelLoading"
|
||||
src="{% static 'images/loading.gif' %}">
|
||||
<p>{% trans "Set limits and view usage for " %} <span id="domain">{{ domain }}</span></p>
|
||||
</div>
|
||||
|
||||
<button style="margin-bottom: 2%" class="btn btn-warning" data-toggle="modal" data-target="#settings"><i
|
||||
class="fa fa-gear"></i> Edit Limits
|
||||
</button>
|
||||
|
||||
<div ng-hide="limitsInfoBox" class="form-group">
|
||||
<div class="alert alert-info">
|
||||
<p>{% trans "Limits are not being inforced, click Edit Limits to inforace the limits." %}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<table cellpadding="0" cellspacing="0" border="0" class="table table-striped table-bordered"
|
||||
id="datatable-example">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{% trans 'Limit' %}</th>
|
||||
<th>{% trans 'Value' %}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
||||
<tr>
|
||||
<td>{% trans 'CPU Percentage' %}</td>
|
||||
<td>{$ cpuPers $}%</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{% trans 'Memory' %}</td>
|
||||
<td>{$ memory $}MB</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{% trans 'I/O' %}</td>
|
||||
<td>{$ IO $}MB/sec</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{% trans 'IOPS' %}</td>
|
||||
<td>{$ IOPS $}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{% trans 'Network Speed' %}</td>
|
||||
<td>{$ networkSpeed $}</td>
|
||||
</tr>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
<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">×</button>
|
||||
<h4 class="modal-title">Website Limits
|
||||
<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 "CPU Percentage" %}</label>
|
||||
<div class="col-sm-6">
|
||||
<input name="memory" type="number" class="form-control" ng-model="cpuPers" required>
|
||||
</div>
|
||||
<div class="current-pack ng-binding">%</div>
|
||||
</div>
|
||||
<div ng-hide="installationDetailsForm" class="form-group">
|
||||
<label class="col-sm-3 control-label">{% trans "Memory Limit" %}</label>
|
||||
<div class="col-sm-6">
|
||||
<input name="memory" type="number" class="form-control" ng-model="memory" required>
|
||||
</div>
|
||||
<div class="current-pack ng-binding">MB</div>
|
||||
</div>
|
||||
<div ng-hide="installationDetailsForm" class="form-group">
|
||||
<label class="col-sm-3 control-label">{% trans "I/O" %}</label>
|
||||
<div class="col-sm-6">
|
||||
<input name="memory" type="number" class="form-control" ng-model="IO" required>
|
||||
</div>
|
||||
<div class="current-pack ng-binding">MB</div>
|
||||
</div>
|
||||
|
||||
<div ng-hide="installationDetailsForm" class="form-group">
|
||||
<label class="col-sm-3 control-label">{% trans "IOPS" %}</label>
|
||||
<div class="col-sm-6">
|
||||
<input name="memory" type="number" class="form-control" ng-model="IOPS" required>
|
||||
</div>
|
||||
<div class="current-pack ng-binding">Operations</div>
|
||||
</div>
|
||||
|
||||
<div ng-hide="installationDetailsForm" class="form-group">
|
||||
<label class="col-sm-3 control-label">{% trans "Network Speed" %}</label>
|
||||
<div class="col-sm-4">
|
||||
<input name="memory" type="number" class="form-control" ng-model="networkSpeedBox"
|
||||
required>
|
||||
</div>
|
||||
<div class="col-sm-2">
|
||||
<select ng-model="networkHandle" class="form-control">
|
||||
<option>kbps</option>
|
||||
<option>mbit</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
|
||||
<div ng-hide="installationDetailsForm" class="form-group">
|
||||
<label class="col-sm-3 control-label">Enforce Limits</label>
|
||||
<div class="col-sm-9">
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input ng-model="enforce" type="checkbox" value=""
|
||||
class="ng-pristine ng-untouched ng-valid ng-empty">
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<br>
|
||||
|
||||
</form>
|
||||
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-primary"
|
||||
ng-click="saveWebsiteLimits()" data-dismiss="modal">Save
|
||||
</button>
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">
|
||||
Close
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</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
containerization/tests.py
Normal file
6
containerization/tests.py
Normal file
@@ -0,0 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
||||
11
containerization/urls.py
Normal file
11
containerization/urls.py
Normal file
@@ -0,0 +1,11 @@
|
||||
from django.conf.urls import url
|
||||
import views
|
||||
|
||||
urlpatterns = [
|
||||
url(r'^$', views.cHome, name='cHome'),
|
||||
url(r'^submitContainerInstall$', views.submitContainerInstall, name='submitContainerInstall'),
|
||||
url(r'^manage/(?P<domain>(.*))$', views.websiteContainerLimit, name='websiteContainerLimit'),
|
||||
url(r'^fetchWebsiteLimits$', views.fetchWebsiteLimits, name='fetchWebsiteLimits'),
|
||||
url(r'^saveWebsiteLimits$', views.saveWebsiteLimits, name='saveWebsiteLimits'),
|
||||
url(r'^getUsageData$', views.getUsageData, name='getUsageData'),
|
||||
]
|
||||
351
containerization/views.py
Normal file
351
containerization/views.py
Normal file
@@ -0,0 +1,351 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.shortcuts import HttpResponse, redirect
|
||||
from loginSystem.views import loadLoginPage
|
||||
from containerManager import ContainerManager
|
||||
import json
|
||||
from websiteFunctions.models import Websites
|
||||
from .models import ContainerLimits
|
||||
from random import randint
|
||||
from plogical.processUtilities import ProcessUtilities
|
||||
import os
|
||||
import subprocess
|
||||
import multiprocessing
|
||||
from plogical.httpProc import httpProc
|
||||
from plogical.acl import ACLManager
|
||||
# Create your views here.
|
||||
|
||||
def cHome(request):
|
||||
try:
|
||||
templateName = 'containerization/listWebsites.html'
|
||||
c = ContainerManager(request, templateName)
|
||||
return c.renderC()
|
||||
except KeyError:
|
||||
return redirect(loadLoginPage)
|
||||
|
||||
def submitContainerInstall(request):
|
||||
try:
|
||||
|
||||
userID = request.session['userID']
|
||||
currentACL = ACLManager.loadedACL(userID)
|
||||
|
||||
if currentACL['admin'] == 1:
|
||||
pass
|
||||
else:
|
||||
return ACLManager.loadErrorJson()
|
||||
|
||||
c = ContainerManager(request, None, 'submitContainerInstall')
|
||||
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 websiteContainerLimit(request, domain):
|
||||
try:
|
||||
templateName = 'containerization/websiteContainerLimit.html'
|
||||
data = {}
|
||||
data['domain'] = domain
|
||||
c = ContainerManager(request, templateName, None, data)
|
||||
return c.renderC()
|
||||
except KeyError:
|
||||
return redirect(loadLoginPage)
|
||||
|
||||
def fetchWebsiteLimits(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)
|
||||
|
||||
try:
|
||||
websiteLimits = ContainerLimits.objects.get(owner=website)
|
||||
except:
|
||||
confPathTemp = "/home/cyberpanel/" + str(randint(1000, 9999))
|
||||
confPath = '/etc/cgconfig.d/' + domain
|
||||
count = ContainerLimits.objects.all().count() + 1
|
||||
hexValue = ContainerManager.fetchHexValue(count)
|
||||
cfs_quota_us = multiprocessing.cpu_count() * 10000
|
||||
finalContent = ContainerManager.prepConf(website.externalApp, str(cfs_quota_us), str(100000), str(356), 1, 1024, hexValue)
|
||||
|
||||
if finalContent == 0:
|
||||
return httpProc.AJAX(0, 'Please check CyberPanel main log file.')
|
||||
|
||||
|
||||
writeToFile = open(confPathTemp, 'w')
|
||||
writeToFile.write(finalContent)
|
||||
writeToFile.close()
|
||||
|
||||
command = 'sudo mv ' + confPathTemp + ' ' + confPath
|
||||
ProcessUtilities.executioner(command)
|
||||
|
||||
try:
|
||||
os.remove(confPathTemp)
|
||||
except:
|
||||
pass
|
||||
|
||||
websiteLimits = ContainerLimits(owner=website, cpuPers='10', IO='1', IOPS='1024', memory='300', networkSpeed='1mbit', networkHexValue=hexValue)
|
||||
websiteLimits.save()
|
||||
|
||||
finalData = {}
|
||||
finalData['status'] = 1
|
||||
finalData['cpuPers'] = int(websiteLimits.cpuPers)
|
||||
finalData['IO'] = int(websiteLimits.IO)
|
||||
finalData['IOPS'] = int(websiteLimits.IOPS)
|
||||
finalData['memory'] = int(websiteLimits.memory)
|
||||
finalData['networkSpeed'] = websiteLimits.networkSpeed
|
||||
|
||||
if websiteLimits.enforce == 1:
|
||||
finalData['enforce'] = 1
|
||||
else:
|
||||
finalData['enforce'] = 0
|
||||
|
||||
json_data = json.dumps(finalData)
|
||||
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 saveWebsiteLimits(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']
|
||||
cpuPers = data['cpuPers']
|
||||
IO = data['IO']
|
||||
IOPS = data['IOPS']
|
||||
memory = data['memory']
|
||||
networkSpeed = data['networkSpeed']
|
||||
networkHandle = data['networkHandle']
|
||||
|
||||
try:
|
||||
enforce = data['enforce']
|
||||
except:
|
||||
enforce = False
|
||||
|
||||
if cpuPers > 100:
|
||||
return httpProc.AJAX(0, 'CPU Percentage can not be greater then 100%')
|
||||
|
||||
website = Websites.objects.get(domain=domain)
|
||||
websiteLimits = ContainerLimits.objects.get(owner=website)
|
||||
|
||||
|
||||
if enforce == True:
|
||||
if websiteLimits.enforce == 0:
|
||||
|
||||
cgrulesTemp = "/home/cyberpanel/" + str(randint(1000, 9999))
|
||||
cgrules = '/etc/cgrules.conf'
|
||||
enforceString = '{} cpu,memory,blkio,net_cls {}/\n'.format(website.externalApp, website.externalApp)
|
||||
|
||||
cgrulesData = ProcessUtilities.outputExecutioner('sudo cat /etc/cgrules.conf').splitlines()
|
||||
|
||||
writeToFile = open(cgrulesTemp, 'w')
|
||||
|
||||
for items in cgrulesData:
|
||||
writeToFile.writelines(items + '\n')
|
||||
|
||||
writeToFile.writelines(enforceString)
|
||||
writeToFile.close()
|
||||
|
||||
command = 'sudo mv ' + cgrulesTemp + ' ' + cgrules
|
||||
ProcessUtilities.executioner(command)
|
||||
|
||||
try:
|
||||
os.remove(cgrulesTemp)
|
||||
except:
|
||||
pass
|
||||
|
||||
websiteLimits.enforce = 1
|
||||
|
||||
## Main Conf File
|
||||
|
||||
confPathTemp = "/home/cyberpanel/" + str(randint(1000, 9999))
|
||||
confPath = '/etc/cgconfig.d/' + domain
|
||||
cfs_quota_us = multiprocessing.cpu_count() * 1000
|
||||
finalContent = ContainerManager.prepConf(website.externalApp, str(cpuPers * cfs_quota_us), str(100000),
|
||||
str(memory), IO, IOPS, websiteLimits.networkHexValue)
|
||||
|
||||
if finalContent == 0:
|
||||
return httpProc.AJAX(0, 'Please check CyberPanel main log file.')
|
||||
|
||||
writeToFile = open(confPathTemp, 'w')
|
||||
writeToFile.write(finalContent)
|
||||
writeToFile.close()
|
||||
|
||||
command = 'sudo mv ' + confPathTemp + ' ' + confPath
|
||||
ProcessUtilities.executioner(command)
|
||||
|
||||
try:
|
||||
os.remove(confPathTemp)
|
||||
except:
|
||||
pass
|
||||
|
||||
## Add Traffic Control / Restart Services
|
||||
|
||||
additionalArgs = {}
|
||||
additionalArgs['classID'] = websiteLimits.id
|
||||
additionalArgs['rateLimit'] = str(networkSpeed) + networkHandle
|
||||
|
||||
c = ContainerManager(None, None, 'addTrafficController', additionalArgs)
|
||||
c.start()
|
||||
else:
|
||||
websiteLimits.enforce = 0
|
||||
|
||||
cgrulesTemp = "/home/cyberpanel/" + str(randint(1000, 9999))
|
||||
cgrules = '/etc/cgrules.conf'
|
||||
|
||||
cgrulesData = ProcessUtilities.outputExecutioner('sudo cat /etc/cgrules.conf').splitlines()
|
||||
|
||||
writeToFile = open(cgrulesTemp, 'w')
|
||||
|
||||
for items in cgrulesData:
|
||||
if items.find(website.externalApp) > -1:
|
||||
continue
|
||||
writeToFile.writelines(items + '\n')
|
||||
|
||||
writeToFile.close()
|
||||
|
||||
command = 'sudo mv ' + cgrulesTemp + ' ' + cgrules
|
||||
ProcessUtilities.executioner(command)
|
||||
|
||||
confPath = '/etc/cgconfig.d/' + domain
|
||||
|
||||
command = 'sudo rm ' + confPath
|
||||
ProcessUtilities.executioner(command)
|
||||
|
||||
## Not needed, to be removed later
|
||||
|
||||
additionalArgs = {}
|
||||
additionalArgs['classID'] = websiteLimits.id
|
||||
|
||||
c = ContainerManager(None, None, 'removeLimits', additionalArgs)
|
||||
c.start()
|
||||
|
||||
try:
|
||||
os.remove(cgrulesTemp)
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
|
||||
websiteLimits.cpuPers = str(cpuPers)
|
||||
websiteLimits.memory = str(memory)
|
||||
websiteLimits.IO = str(IO)
|
||||
websiteLimits.IOPS = str(IOPS)
|
||||
websiteLimits.networkSpeed = str(networkSpeed) + str(networkHandle)
|
||||
websiteLimits.save()
|
||||
|
||||
finalData = {}
|
||||
finalData['status'] = 1
|
||||
json_data = json.dumps(finalData)
|
||||
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 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)
|
||||
|
||||
try:
|
||||
type = data['type']
|
||||
finalData = {}
|
||||
finalData['status'] = 1
|
||||
|
||||
try:
|
||||
if type == 'memory':
|
||||
|
||||
command = 'sudo cat /sys/fs/cgroup/memory/' + website.externalApp + '/memory.usage_in_bytes'
|
||||
output = str(ProcessUtilities.outputExecutioner(command))
|
||||
finalData['memory'] = int(float(output)/float(1024 * 1024))
|
||||
|
||||
elif type == 'io':
|
||||
|
||||
path = '/home/cyberpanel/' + website.externalApp
|
||||
blkioPath = path + '/blkio'
|
||||
|
||||
if not os.path.exists(path):
|
||||
os.mkdir(path)
|
||||
|
||||
command = 'sudo cat /sys/fs/cgroup/blkio/' + website.externalApp + '/blkio.throttle.io_service_bytes'
|
||||
output = ProcessUtilities.outputExecutioner(command).splitlines()
|
||||
|
||||
readCurrent = output[0].split(' ')[2]
|
||||
writeCurrent = output[1].split(' ')[2]
|
||||
|
||||
if os.path.exists(blkioPath):
|
||||
|
||||
old = open(blkioPath, 'r').read()
|
||||
oldRead = float(old.split(',')[0])
|
||||
oldWrite = float(old.split(',')[1])
|
||||
|
||||
finalData['readRate'] = int((float(readCurrent) - oldRead)/float(65536000))
|
||||
finalData['writeRate'] = int((float(writeCurrent) - oldWrite) / float(65536000))
|
||||
|
||||
else:
|
||||
finalData['readRate'] = 0
|
||||
finalData['writeRate'] = 0
|
||||
|
||||
writeToFile = open(blkioPath, 'w')
|
||||
writeToFile.write(readCurrent + ',' + writeCurrent)
|
||||
writeToFile.close()
|
||||
|
||||
except:
|
||||
finalData['memory'] = '0'
|
||||
finalData['readRate'] = 0
|
||||
finalData['writeRate'] = 0
|
||||
except:
|
||||
command = "top -b -n 1 -u " + website.externalApp + " | awk 'NR>7 { sum += $9; } END { print sum; }'"
|
||||
output = str(subprocess.check_output(command, shell=True))
|
||||
|
||||
finalData = {}
|
||||
finalData['status'] = 1
|
||||
if len(output) == 0:
|
||||
finalData['cpu'] = '0'
|
||||
else:
|
||||
finalData['cpu'] = str(float(output)/float(multiprocessing.cpu_count()))
|
||||
|
||||
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)
|
||||
Reference in New Issue
Block a user