From 88b95d511fab026ac3c28fe420259f684579e060 Mon Sep 17 00:00:00 2001 From: usmannasir <01-134132-158@student.bahria.edu.pk> Date: Mon, 10 Sep 2018 01:45:43 +0500 Subject: [PATCH] Virtual machine manager --- CyberCP/settings.py | 8 +- CyberCP/urls.py | 3 + CyberTronAPI/CyberTronLogger.py | 35 + CyberTronAPI/__init__.py | 0 CyberTronAPI/cybertron.py | 489 ++++++++ CyberTronAPI/hashPassword.py | 13 + CyberTronAPI/logLevel.py | 2 + CyberTronAPI/randomPassword.py | 38 + CyberTronAPI/sslUtilities.py | 341 ++++++ CyberTronAPI/test.py | 29 + CyberTronAPI/virtualMachineAPI.py | 638 ++++++++++ CyberTronAPI/virtualMachineAPIKVM.py | 613 ++++++++++ CyberTronAPI/virtualMachineAPIOpenVZ.py | 668 ++++++++++ backup/static/backup/backup.js | 478 +++++++- backup/templates/backup/createSnapshots.html | 99 ++ backup/urls.py | 8 + backup/views.py | 50 +- .../templates/baseTemplate/homePageVMM.html | 85 ++ .../templates/baseTemplate/index.html | 16 +- .../templates/baseTemplate/indexVMM.html | 392 ++++++ baseTemplate/urls.py | 7 +- baseTemplate/views.py | 25 +- hypervisor/__init__.py | 0 hypervisor/admin.py | 6 + hypervisor/apps.py | 8 + hypervisor/hypervisor.py | 144 +++ hypervisor/migrations/__init__.py | 0 hypervisor/models.py | 13 + hypervisor/static/hypervisor/hypervisor.js | 287 +++++ .../hypervisor/createHyperVisor.html | 91 ++ hypervisor/templates/hypervisor/indexVMM.html | 56 + hypervisor/templates/hypervisor/listHV.html | 147 +++ hypervisor/tests.py | 6 + hypervisor/urls.py | 12 + hypervisor/views.py | 56 + install/install.py | 297 ++++- install/openlitespeed.tar.gz | Bin 4090810 -> 4090810 bytes ipManagement/__init__.py | 0 ipManagement/admin.py | 6 + ipManagement/apps.py | 8 + ipManagement/migrations/__init__.py | 0 ipManagement/models.py | 20 + .../static/ipManagement/ipManagement.js | 458 +++++++ .../templates/ipManagement/createIPPool.html | 114 ++ .../templates/ipManagement/indexVMM.html | 56 + .../templates/ipManagement/listIPPools.html | 209 ++++ ipManagement/tests.py | 6 + ipManagement/urls.py | 23 + ipManagement/views.py | 335 ++++++ packages/models.py | 9 + packages/static/packages/packages.js | 312 ++++- .../templates/packages/createPackageVMM.html | 102 ++ .../templates/packages/deletePackageVMM.html | 85 ++ packages/templates/packages/indexVMM.html | 70 ++ .../templates/packages/modifyPackageVMM.html | 122 ++ packages/urls.py | 23 +- packages/views.py | 212 +++- plogical/.my.cnf.4370 | 0 plogical/.mysql.4370 | 0 plogical/CyberCPLogFileWriter.py | 0 plogical/__init__.py | 0 plogical/acl.py | 0 plogical/aclVMM.py | 277 +++++ plogical/adminPass.py | 0 plogical/alias.py | 0 plogical/applicationInstaller.py | 0 plogical/backupManager.py | 3 + plogical/backupSchedule.py | 0 plogical/backupScheduleLocal.py | 0 plogical/backupUtilities.py | 0 plogical/childDomain.py | 0 plogical/dnsUtilities.py | 0 plogical/domain.xml | 0 plogical/filemanager.py | 0 plogical/findBWUsage.py | 0 plogical/firewallManager.py | 0 plogical/firewallUtilities.py | 0 plogical/ftpUtilities.py | 0 plogical/getSystemInformation.py | 0 plogical/hashPassword.py | 0 plogical/installUtilities.py | 0 plogical/letsEncrypt.py | 0 plogical/mailUtilities.py | 0 plogical/modSec.py | 0 plogical/mysqlUtilities.py | 1 - plogical/phpUtilities.py | 0 plogical/processUtilities.py | 0 plogical/randomPassword.py | 0 plogical/remoteBackup.py | 0 plogical/remoteTransferUtilities.py | 0 plogical/serverLogs.py | 0 plogical/sslUtilities.py | 0 plogical/test.py | 0 plogical/tuning.py | 0 plogical/upgrade.py | 0 plogical/vhost.py | 0 plogical/virtualHostUtilities.py | 21 + plogical/website.py | 4 +- requirments.txt | 1 + static/backup/backup.js | 478 +++++++- static/hypervisor/hypervisor.js | 287 +++++ static/ipManagement/ipManagement.js | 458 +++++++ static/packages/packages.js | 312 ++++- static/userManagment/userManagment.js | 2 +- static/vpsManagement/backup.png | Bin 0 -> 2414 bytes static/vpsManagement/changePassword.png | Bin 0 -> 2919 bytes static/vpsManagement/close-32.png | Bin 0 -> 1039 bytes static/vpsManagement/console.png | Bin 0 -> 1111 bytes static/vpsManagement/delete.png | Bin 0 -> 894 bytes static/vpsManagement/hostname.png | Bin 0 -> 2891 bytes static/vpsManagement/install.png | Bin 0 -> 1910 bytes static/vpsManagement/pnotify.custom.min.css | 10 + static/vpsManagement/pnotify.custom.min.js | 31 + static/vpsManagement/powerOff.png | Bin 0 -> 599 bytes static/vpsManagement/restart.png | Bin 0 -> 903 bytes static/vpsManagement/settings-gears.png | Bin 0 -> 1228 bytes static/vpsManagement/snapshots.png | Bin 0 -> 988 bytes static/vpsManagement/vpsManagement.js | 1041 ++++++++++++++++ static/vpsManagement/vpsON.png | Bin 0 -> 757 bytes static/vpsManagement/vpsOff.png | Bin 0 -> 667 bytes .../static/userManagment/userManagment.js | 2 +- vpsManagement/__init__.py | 0 vpsManagement/admin.py | 6 + vpsManagement/apps.py | 8 + vpsManagement/migrations/__init__.py | 0 vpsManagement/models.py | 33 + vpsManagement/static/vpsManagement/backup.png | Bin 0 -> 2414 bytes .../static/vpsManagement/changePassword.png | Bin 0 -> 2919 bytes .../static/vpsManagement/close-32.png | Bin 0 -> 1039 bytes .../static/vpsManagement/console.png | Bin 0 -> 1111 bytes vpsManagement/static/vpsManagement/delete.png | Bin 0 -> 894 bytes .../static/vpsManagement/hostname.png | Bin 0 -> 2891 bytes .../static/vpsManagement/install.png | Bin 0 -> 1910 bytes .../vpsManagement/pnotify.custom.min.css | 10 + .../vpsManagement/pnotify.custom.min.js | 31 + .../static/vpsManagement/powerOff.png | Bin 0 -> 599 bytes .../static/vpsManagement/restart.png | Bin 0 -> 903 bytes .../static/vpsManagement/settings-gears.png | Bin 0 -> 1228 bytes .../static/vpsManagement/snapshots.png | Bin 0 -> 988 bytes .../static/vpsManagement/vpsManagement.js | 1070 +++++++++++++++++ vpsManagement/static/vpsManagement/vpsON.png | Bin 0 -> 757 bytes vpsManagement/static/vpsManagement/vpsOff.png | Bin 0 -> 667 bytes .../templates/vpsManagement/createVPS.html | 193 +++ .../templates/vpsManagement/indexVMM.html | 68 ++ .../templates/vpsManagement/listVPS.html | 161 +++ .../templates/vpsManagement/manageVPS.html | 402 +++++++ .../templates/vpsManagement/sshKeys.html | 84 ++ vpsManagement/tests.py | 6 + vpsManagement/urls.py | 36 + vpsManagement/views.py | 164 +++ vpsManagement/vpsManager.py | 660 ++++++++++ .../websiteFunctions/createWebsite.html | 1 - 152 files changed, 13102 insertions(+), 89 deletions(-) create mode 100755 CyberTronAPI/CyberTronLogger.py create mode 100755 CyberTronAPI/__init__.py create mode 100755 CyberTronAPI/cybertron.py create mode 100755 CyberTronAPI/hashPassword.py create mode 100755 CyberTronAPI/logLevel.py create mode 100755 CyberTronAPI/randomPassword.py create mode 100755 CyberTronAPI/sslUtilities.py create mode 100755 CyberTronAPI/test.py create mode 100755 CyberTronAPI/virtualMachineAPI.py create mode 100755 CyberTronAPI/virtualMachineAPIKVM.py create mode 100755 CyberTronAPI/virtualMachineAPIOpenVZ.py create mode 100644 backup/templates/backup/createSnapshots.html create mode 100644 baseTemplate/templates/baseTemplate/homePageVMM.html create mode 100644 baseTemplate/templates/baseTemplate/indexVMM.html create mode 100644 hypervisor/__init__.py create mode 100644 hypervisor/admin.py create mode 100644 hypervisor/apps.py create mode 100644 hypervisor/hypervisor.py create mode 100644 hypervisor/migrations/__init__.py create mode 100644 hypervisor/models.py create mode 100644 hypervisor/static/hypervisor/hypervisor.js create mode 100644 hypervisor/templates/hypervisor/createHyperVisor.html create mode 100644 hypervisor/templates/hypervisor/indexVMM.html create mode 100644 hypervisor/templates/hypervisor/listHV.html create mode 100644 hypervisor/tests.py create mode 100644 hypervisor/urls.py create mode 100644 hypervisor/views.py create mode 100644 ipManagement/__init__.py create mode 100644 ipManagement/admin.py create mode 100644 ipManagement/apps.py create mode 100644 ipManagement/migrations/__init__.py create mode 100644 ipManagement/models.py create mode 100644 ipManagement/static/ipManagement/ipManagement.js create mode 100644 ipManagement/templates/ipManagement/createIPPool.html create mode 100644 ipManagement/templates/ipManagement/indexVMM.html create mode 100644 ipManagement/templates/ipManagement/listIPPools.html create mode 100644 ipManagement/tests.py create mode 100644 ipManagement/urls.py create mode 100644 ipManagement/views.py create mode 100644 packages/templates/packages/createPackageVMM.html create mode 100644 packages/templates/packages/deletePackageVMM.html create mode 100644 packages/templates/packages/indexVMM.html create mode 100644 packages/templates/packages/modifyPackageVMM.html mode change 100644 => 100755 plogical/.my.cnf.4370 mode change 100644 => 100755 plogical/.mysql.4370 mode change 100644 => 100755 plogical/CyberCPLogFileWriter.py mode change 100644 => 100755 plogical/__init__.py mode change 100644 => 100755 plogical/acl.py create mode 100755 plogical/aclVMM.py mode change 100644 => 100755 plogical/adminPass.py mode change 100644 => 100755 plogical/alias.py mode change 100644 => 100755 plogical/applicationInstaller.py mode change 100644 => 100755 plogical/backupManager.py mode change 100644 => 100755 plogical/backupSchedule.py mode change 100644 => 100755 plogical/backupScheduleLocal.py mode change 100644 => 100755 plogical/backupUtilities.py mode change 100644 => 100755 plogical/childDomain.py mode change 100644 => 100755 plogical/dnsUtilities.py mode change 100644 => 100755 plogical/domain.xml mode change 100644 => 100755 plogical/filemanager.py mode change 100644 => 100755 plogical/findBWUsage.py mode change 100644 => 100755 plogical/firewallManager.py mode change 100644 => 100755 plogical/firewallUtilities.py mode change 100644 => 100755 plogical/ftpUtilities.py mode change 100644 => 100755 plogical/getSystemInformation.py mode change 100644 => 100755 plogical/hashPassword.py mode change 100644 => 100755 plogical/installUtilities.py mode change 100644 => 100755 plogical/letsEncrypt.py mode change 100644 => 100755 plogical/mailUtilities.py mode change 100644 => 100755 plogical/modSec.py mode change 100644 => 100755 plogical/mysqlUtilities.py mode change 100644 => 100755 plogical/phpUtilities.py mode change 100644 => 100755 plogical/processUtilities.py mode change 100644 => 100755 plogical/randomPassword.py mode change 100644 => 100755 plogical/remoteBackup.py mode change 100644 => 100755 plogical/remoteTransferUtilities.py mode change 100644 => 100755 plogical/serverLogs.py mode change 100644 => 100755 plogical/sslUtilities.py mode change 100644 => 100755 plogical/test.py mode change 100644 => 100755 plogical/tuning.py mode change 100644 => 100755 plogical/upgrade.py mode change 100644 => 100755 plogical/vhost.py mode change 100644 => 100755 plogical/virtualHostUtilities.py mode change 100644 => 100755 plogical/website.py create mode 100644 static/hypervisor/hypervisor.js create mode 100644 static/ipManagement/ipManagement.js create mode 100644 static/vpsManagement/backup.png create mode 100644 static/vpsManagement/changePassword.png create mode 100644 static/vpsManagement/close-32.png create mode 100644 static/vpsManagement/console.png create mode 100644 static/vpsManagement/delete.png create mode 100644 static/vpsManagement/hostname.png create mode 100644 static/vpsManagement/install.png create mode 100644 static/vpsManagement/pnotify.custom.min.css create mode 100644 static/vpsManagement/pnotify.custom.min.js create mode 100644 static/vpsManagement/powerOff.png create mode 100644 static/vpsManagement/restart.png create mode 100644 static/vpsManagement/settings-gears.png create mode 100644 static/vpsManagement/snapshots.png create mode 100644 static/vpsManagement/vpsManagement.js create mode 100644 static/vpsManagement/vpsON.png create mode 100644 static/vpsManagement/vpsOff.png create mode 100644 vpsManagement/__init__.py create mode 100644 vpsManagement/admin.py create mode 100644 vpsManagement/apps.py create mode 100644 vpsManagement/migrations/__init__.py create mode 100644 vpsManagement/models.py create mode 100644 vpsManagement/static/vpsManagement/backup.png create mode 100644 vpsManagement/static/vpsManagement/changePassword.png create mode 100644 vpsManagement/static/vpsManagement/close-32.png create mode 100644 vpsManagement/static/vpsManagement/console.png create mode 100644 vpsManagement/static/vpsManagement/delete.png create mode 100644 vpsManagement/static/vpsManagement/hostname.png create mode 100644 vpsManagement/static/vpsManagement/install.png create mode 100644 vpsManagement/static/vpsManagement/pnotify.custom.min.css create mode 100644 vpsManagement/static/vpsManagement/pnotify.custom.min.js create mode 100644 vpsManagement/static/vpsManagement/powerOff.png create mode 100644 vpsManagement/static/vpsManagement/restart.png create mode 100644 vpsManagement/static/vpsManagement/settings-gears.png create mode 100644 vpsManagement/static/vpsManagement/snapshots.png create mode 100644 vpsManagement/static/vpsManagement/vpsManagement.js create mode 100644 vpsManagement/static/vpsManagement/vpsON.png create mode 100644 vpsManagement/static/vpsManagement/vpsOff.png create mode 100644 vpsManagement/templates/vpsManagement/createVPS.html create mode 100644 vpsManagement/templates/vpsManagement/indexVMM.html create mode 100644 vpsManagement/templates/vpsManagement/listVPS.html create mode 100644 vpsManagement/templates/vpsManagement/manageVPS.html create mode 100644 vpsManagement/templates/vpsManagement/sshKeys.html create mode 100644 vpsManagement/tests.py create mode 100644 vpsManagement/urls.py create mode 100644 vpsManagement/views.py create mode 100644 vpsManagement/vpsManager.py diff --git a/CyberCP/settings.py b/CyberCP/settings.py index 20c3aba70..a28cda9eb 100644 --- a/CyberCP/settings.py +++ b/CyberCP/settings.py @@ -24,7 +24,7 @@ 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 = ['*'] @@ -58,8 +58,12 @@ INSTALLED_APPS = [ 'manageSSL', 'api', 'filemanager', - 'manageServices', 'emailPremium', + 'manageServices', + 'ipManagement', + 'vpsManagement', + 'hypervisor' + ] MIDDLEWARE = [ diff --git a/CyberCP/urls.py b/CyberCP/urls.py index 3780c7b72..1c7b2c2f8 100644 --- a/CyberCP/urls.py +++ b/CyberCP/urls.py @@ -37,4 +37,7 @@ urlpatterns = [ url(r'^filemanager/',include('filemanager.urls')), url(r'^emailPremium/',include('emailPremium.urls')), url(r'^manageservices/',include('manageServices.urls')), + url(r'^ip/', include('ipManagement.urls')), + url(r'^vps/',include('vpsManagement.urls')), + url(r'^hv/',include('hypervisor.urls')), ] diff --git a/CyberTronAPI/CyberTronLogger.py b/CyberTronAPI/CyberTronLogger.py new file mode 100755 index 000000000..f38b111c8 --- /dev/null +++ b/CyberTronAPI/CyberTronLogger.py @@ -0,0 +1,35 @@ +import subprocess +import time + +class CyberTronLogger: + fileName = "/home/cyberpanel/error-logs.txt" + operationsLogFile = "/home/cyberpanel/error-logs.txt" + + @staticmethod + def writeToFile(message,level,method): + try: + file = open(CyberTronLogger.fileName,'a') + file.writelines("[" + time.strftime( + "%I-%M-%S-%a-%b-%Y") + "] [" + level + ":" + method + "] " + message + "\n") + file.close() + file.close() + except IOError: + return "Can not write to error file!" + + @staticmethod + def operationsLog(message,level,method): + try: + file = open(CyberTronLogger.operationsLogFile, 'a') + file.writelines("[" + time.strftime( + "%I-%M-%S-%a-%b-%Y") + "] [" + level + ":"+ method + "] " + message + "\n") + file.close() + except IOError: + return "Can not write to error file!" + + @staticmethod + def readLastNFiles(numberOfLines,fileName): + try: + lastFewLines = subprocess.check_output(["tail", "-n",str(numberOfLines),fileName]) + return lastFewLines + except subprocess.CalledProcessError: + return "File was empty!" \ No newline at end of file diff --git a/CyberTronAPI/__init__.py b/CyberTronAPI/__init__.py new file mode 100755 index 000000000..e69de29bb diff --git a/CyberTronAPI/cybertron.py b/CyberTronAPI/cybertron.py new file mode 100755 index 000000000..ffa424b3d --- /dev/null +++ b/CyberTronAPI/cybertron.py @@ -0,0 +1,489 @@ +#!/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 CyberTronLogger import CyberTronLogger as logger +from inspect import stack +from shlex import split +from subprocess import call,CalledProcessError +from os.path import join +from random import randint +from logLevel import logLevel +from ipManagement.models import IPAddresses +from packages.models import VMPackage as Package +from django.db.models import Max +import CyberTronAPI.randomPassword as randomPassword +from vpsManagement.models import VPS, SSHKeys +from loginSystem.models import Administrator +from CyberTronAPI.virtualMachineAPIKVM import virtualMachineAPI +import plogical.CyberCPLogFileWriter as logging +from os import remove + + +class CyberTron(multi.Thread): + imagesPath = join('/var', 'lib', 'libvirt', 'images') + templatesPath = join('/var', 'lib', 'libvirt', 'templates') + + def __init__(self, data): + multi.Thread.__init__(self) + self.data = data + + def run(self): + try: + self.createVirtualMachine(self.data) + except BaseException, msg: + logger.writeToFile(str(msg), "Error", stack()[0][3]) + + def setupNetworkingFiles(self, ipAddress, osName, ipPool, hostName, tempStatusPath): + try: + + if logLevel.debug == True: + logger.operationsLog('Setting up network for: ' + ipAddress + '.', 'Debug', stack()[0][3]) + + uploadSource = [] + + ## Set Device name + deviceName = '' + + if osName == 'centos-6': + deviceName = 'eth0' + elif osName == 'centos-7.2': + deviceName = 'ens3' + elif osName == 'debian-9' or osName == 'ubuntu-16.04': + deviceName = 'ens3' + + + if osName.find("centos") > -1: + ###### /etc/sysconfig/network-scripts/ifcfg-eth0 + + eth0 = "/home/cyberpanel/ifcfg-ens3" + str(randint(10000, 99999)) + eth0File = open(eth0, 'w') + + eth0File.writelines('DEVICE="' + deviceName + '"\n') + eth0File.writelines('NM_CONTROLLED="yes"\n') + eth0File.writelines('ONBOOT=yes\n') + eth0File.writelines('TYPE=Ethernet\n') + eth0File.writelines('BOOTPROTO=static\n') + eth0File.writelines('NAME="System ' + deviceName + '"\n') + eth0File.writelines('IPADDR=' + ipAddress + '\n') + eth0File.writelines('NETMASK=' + ipPool.netmask + '\n') + + eth0File.close() + + uploadSource.append(eth0) + + ###### /etc/sysconfig/network + + network = "/home/cyberpanel/network_" + str(randint(10000, 99999) + 1) + networkFile = open(network, 'w') + + networkFile.writelines('NETWORKING=yes\n') + networkFile.writelines('HOSTNAME=' + hostName + '\n') + networkFile.writelines('GATEWAY=' + ipPool.gateway + '\n') + + networkFile.close() + + uploadSource.append(network) + + ###### /etc/resolv.conf + + resolv = "/home/cyberpanel/resolv_" + str(randint(10000, 99999) + 2) + resolvFile = open(resolv, 'w') + + resolvFile.writelines("nameserver 8.8.8.8\n") + + resolvFile.close() + + uploadSource.append(resolv) + elif osName == 'ubuntu-18.04': + + eth0 = "/home/cyberpanel/interfaces_" + str(randint(10000, 99999)) + eth0File = open(eth0, 'w') + + eth0File.writelines('# This file describes the network interfaces available on your system\n') + eth0File.writelines('# For more information, see netplan(5).\n') + + eth0File.writelines('\n') + + eth0File.writelines('network:\n') + eth0File.writelines(' version: 2\n') + eth0File.writelines(' renderer: networkd\n') + eth0File.writelines(' ethernets:\n') + eth0File.writelines(' ens2:\n') + eth0File.writelines(' dhcp4: yes\n') + eth0File.writelines(' ens3:\n') + eth0File.writelines(' dhcp4: no\n') + eth0File.writelines(' addresses: [' + ipAddress + '/24]\n') + eth0File.writelines(' gateway4: ' + ipPool.gateway + '\n') + eth0File.writelines(' nameservers:\n') + eth0File.writelines(' addresses: [8.8.8.8,8.8.4.4]\n') + + eth0File.writelines('\n') + + eth0File.close() + + uploadSource.append(eth0) + elif osName.find("debian") > -1 or osName.find("ubuntu") > -1: + ###### ip + + eth0 = "/home/cyberpanel/interfaces_" + str(randint(10000, 99999)) + eth0File = open(eth0, 'w') + + eth0File.writelines('# This file describes the network interfaces available on your system\n') + eth0File.writelines('# and how to activate them. For more information, see interfaces(5).\n') + + eth0File.writelines('\n') + + eth0File.writelines('# The loopback network interface\n') + eth0File.writelines('auto lo\n') + eth0File.writelines('iface lo inet loopback\n') + + eth0File.writelines('\n') + + ## To deal with Debian 9.3 and ubuntu 16.04 issue. + + eth0File.writelines('# The primary network interface\n') + + + eth0File.writelines('allow-hotplug ' + deviceName + '\n') + eth0File.writelines('iface ' + deviceName + ' inet static\n') + + + eth0File.writelines(' address ' + ipAddress + '\n') + eth0File.writelines(' netmask ' + ipPool.netmask + '\n') + eth0File.writelines(' gateway ' + ipPool.gateway + '\n') + eth0File.writelines('# dns-* options are implemented by the resolvconf package, if installed\n') + eth0File.writelines('dns-nameservers 8.8.8.8\n') + eth0File.writelines('dns-search com\n') + + eth0File.close() + + uploadSource.append(eth0) + elif osName.find("fedora") > -1: + + ###### /etc/sysconfig/network-scripts/ifcfg-ens3 + + eth0 = "/home/cyberpanel/interfaces_" + str(randint(10000, 99999)) + eth0File = open(eth0, 'w') + + eth0File.writelines('TYPE=Ethernet\n') + eth0File.writelines('PROXY_METHOD=none\n') + + eth0File.writelines('BROWSER_ONLY=no\n') + eth0File.writelines('BOOTPROTO=none\n') + eth0File.writelines('DEFROUTE=yes\n') + + eth0File.writelines('IPV4_FAILURE_FATAL=no\n') + eth0File.writelines('IPV6INIT=yes\n') + eth0File.writelines('IPV6_AUTOCONF=yes\n') + + eth0File.writelines('IPV6_DEFROUTE=yes\n') + eth0File.writelines('IPV6_FAILURE_FATAL=no\n') + eth0File.writelines('IPV6_ADDR_GEN_MODE=stable-privacy\n') + eth0File.writelines('NAME=ens3\n') + eth0File.writelines('ONBOOT=yes\n') + eth0File.writelines('AUTOCONNECT_PRIORITY=-999\n') + + eth0File.writelines('DEVICE=ens3\n') + eth0File.writelines('IPADDR=' + ipAddress + '\n') + eth0File.writelines('NETMASK=' + ipPool.netmask + '\n') + eth0File.writelines('GATEWAY=' + ipPool.gateway + '\n') + eth0File.writelines('DNS1=8.8.8.8\n') + eth0File.writelines('IPV6_PRIVACY=no\n') + + eth0File.close() + uploadSource.append(eth0) + elif osName.find("freebsd") > -1: + + ###### /etc/rc.conf + + eth0 = "/home/cyberpanel/ifcfg-eth0_" + str(randint(10000, 99999)) + eth0File = open(eth0, 'w') + + eth0File.writelines('DEVICE="eth0"\n') + eth0File.writelines('NM_CONTROLLED="yes"\n') + eth0File.writelines('ONBOOT=yes\n') + eth0File.writelines('TYPE=Ethernet\n') + eth0File.writelines('BOOTPROTO=static\n') + eth0File.writelines('NAME="System eth0"\n') + eth0File.writelines('IPADDR=' + ipAddress + '\n') + eth0File.writelines('NETMASK=' + ipPool.gateway + '\n') + + eth0File.close() + + uploadSource.append(eth0) + if logLevel.debug == True: + logger.operationsLog('Network settings installed for: ' + ipAddress + '.', 'Debug', stack()[0][3]) + + return uploadSource + + except BaseException, msg: + if logLevel.debug == True: + logger.operationsLog(str(msg), "Error", stack()[0][3]) + logger.writeToFile(str(msg), "Error", stack()[0][3]) + logging.CyberCPLogFileWriter.statusWriter(tempStatusPath, str(msg) + ' [404]') + return 0 + + def buildCustomDisk(self, vmName, osName, size, rootPassword, uploadCommand, tempStatusPath): + try: + + sourcePath = join(virtualMachineAPI.templatesPath, osName + ".img") + tempPath = join(virtualMachineAPI.imagesPath, vmName + "-temp.qcow2") + finalPath = join(virtualMachineAPI.imagesPath, vmName + ".qcow2") + + ## Creating temporary disk image. + + command = "sudo cp " + sourcePath + " " + tempPath + result = call(split(command)) + + if result == 1: + raise CalledProcessError + + if logLevel.debug == True: + logger.operationsLog("Temporary image created for: " + vmName + ".", "Debug", stack()[0][3]) + + command = "sudo qemu-img create -f qcow2 " + finalPath + " " + size + result = call(split(command)) + + if result == 1: + raise CalledProcessError + + if logLevel.debug == True: + logger.operationsLog("Created resized final image for: " + vmName + ".", "Debug", stack()[0][3]) + + command = "sudo virt-resize --expand /dev/sda1 " + tempPath + " " + finalPath + result = call(split(command)) + + if result == 1: + remove(tempPath) + raise CalledProcessError + else: + remove(tempPath) + + if logLevel.debug == True: + logger.operationsLog("Disk resized and ready to use for: " + vmName + ".", "Debug", + stack()[0][3]) + + command = "sudo virt-customize -a " + finalPath + " --root-password password:" + rootPassword + uploadCommand + call(split(command)) + + if result == 1: + raise CalledProcessError + + if logLevel.debug == True: + logger.operationsLog("Root password and network configured for: " + vmName + ".", "Debug", + stack()[0][3]) + return 1 + + + except BaseException, msg: + if logLevel.debug == True: + logger.operationsLog(str(msg), "Error", stack()[0][3]) + logger.writeToFile(str(msg), "Error", stack()[0][3]) + return 0 + except CalledProcessError, msg: + if logLevel.debug == True: + logger.operationsLog(str(msg), "Error", stack()[0][3]) + logger.writeToFile(str(msg), "Error", stack()[0][3]) + logging.CyberCPLogFileWriter.statusWriter(tempStatusPath, str(msg) + ' [404]') + return 0 + + def setupVMDisk(self, vmName, osName, uploadSource, rootPassword, package, tempStatusPath, sshKey = None): + try: + size = package.diskSpace + 'G' + + if osName.find('centos') > -1: + uploadCommand = " --upload " + uploadSource[0] + ":" + "/etc/sysconfig/network-scripts/ifcfg-eth0" + uploadCommand = uploadCommand + " --upload " + uploadSource[1] + ":" + "/etc/sysconfig/network" + uploadCommand = uploadCommand + " --upload " + uploadSource[2] + ":" + "/etc/resolv.conf" + elif osName == 'ubuntu-18.04': + uploadCommand = " --upload " + uploadSource[0] + ":" + "/etc/netplan/01-netcfg.yaml --firstboot-command 'dpkg-reconfigure openssh-server'" + elif osName.find('debian') > -1 or osName.find('ubuntu') > -1: + uploadCommand = " --upload " + uploadSource[0] + ":" + "/etc/network/interfaces --firstboot-command 'ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key && ssh-keygen -t dsa -f /etc/ssh/ssh_host_dsa_key && ssh-keygen -t ecdsa -f /etc/ssh/ssh_host_ecdsa_key'" + elif osName.find('fedora') > -1: + uploadCommand = " --upload " + uploadSource[0] + ":" + "/etc/sysconfig/network-scripts/ifcfg-ens3" + + finalImageLocation = join(CyberTron.imagesPath, vmName + '.qcow2') + + ## "virt-builder centos-7.1 -o /var/lib/libvirt/images192.168.100.1.qcow2 --size 50G --format qcow2 --upload ifcfg-eth0:/etc/sysconfig/network-scripts/ --upload network:/etc/sysconfig + + if osName == 'debian-9' or osName == 'fedora-28' or osName == 'ubuntu-16.04': + self.buildCustomDisk(vmName, osName, size, rootPassword, uploadCommand, tempStatusPath) + else: + if sshKey != None: + command = "sudo virt-builder " + osName + " -o " + finalImageLocation + " --size " + size + \ + " --format qcow2 --root-password password:" + rootPassword + uploadCommand + " --ssh-inject 'root:string:" + sshKey + "'" + else: + command = "sudo virt-builder " + osName + " -o " + finalImageLocation + " --size " + size + \ + " --format qcow2 --root-password password:" + rootPassword + uploadCommand + + result = call(split(command)) + + if result == 1: + raise CalledProcessError + + if logLevel.debug == True: + logger.operationsLog("Disk image created for: " + vmName + ".", "Debug", stack()[0][3]) + + + except BaseException, msg: + if logLevel.debug == True: + logger.operationsLog(str(msg), "Error", stack()[0][3]) + logger.writeToFile(str(msg), "Error", stack()[0][3]) + logging.CyberCPLogFileWriter.statusWriter(tempStatusPath, str(msg) + ' [404]') + return 0 + except CalledProcessError, msg: + if logLevel.debug == True: + logger.operationsLog(str(msg), "Error", stack()[0][3]) + logger.writeToFile(str(msg), "Error", stack()[0][3]) + logging.CyberCPLogFileWriter.statusWriter(tempStatusPath, str(msg) + ' [404]') + return 0 + + def bootVirtualMachine(self, package, vmName, vncHost, vncPort, vncPassword, webSocketPort, hostname, bridgeName, tempStatusPath): + try: + + if logLevel.debug == True: + logger.operationsLog('Booting: ' + vmName + '.', 'Debug', stack()[0][3]) + + finalImageLocation = join(CyberTron.imagesPath, vmName + ".qcow2") + + # virt-install --name 109.238.12.214 --ram 2048 --vcpus=1 --disk 109.238.12.214.qcow2 --graphics vnc,listen=localhost,port=5500 --noautoconsole --hvm --import --os-type=linux --os-variant=rhel7 --network bridge=virbr0 + + command = "sudo virt-install --name " + hostname + " --ram " + str(package.guaranteedRam) + " --vcpu " + str(package.cpuCores) + " --disk " + \ + finalImageLocation + " --graphics vnc,listen=" + vncHost + ",port=" + vncPort + ",password=" + vncPassword + \ + " --noautoconsole --hvm --import --autostart --os-type=linux " \ + + "--network bridge=" + bridgeName + + result = call(split(command)) + + if result == 1: + raise CalledProcessError + + if logLevel.debug == True: + logger.operationsLog("Successfully booted: " + vmName + ".", "Debug", stack()[0][3]) + + return 1 + + except BaseException, msg: + if logLevel.debug == True: + logger.operationsLog(str(msg), "Error", stack()[0][3]) + logger.writeToFile(str(msg), "Error", stack()[0][3]) + logging.CyberCPLogFileWriter.statusWriter(tempStatusPath, str(msg) + ' [404]') + return 0 + except CalledProcessError, msg: + if logLevel.debug == True: + logger.operationsLog(str(msg), "Error", stack()[0][3]) + logger.writeToFile(str(msg), "Error", stack()[0][3]) + logging.CyberCPLogFileWriter.statusWriter(tempStatusPath, str(msg) + ' [404]') + return 0 + + def createVirtualMachine(self, data): + try: + + osName = data['osName'] + vpsPackage = data['vpsPackage'] + vpsOwner = data['vpsOwner'] + vpsIP = data['vpsIP'] + hostname = data['hostname'] + rootPassword = data['rootPassword'] + networkSpeed = data['networkSpeed'] + + logging.CyberCPLogFileWriter.statusWriter(data['tempStatusPath'], 'Running some checks..,0') + + try: + sshKey = data['sshKey'] + key = SSHKeys.objects.get(keyName=sshKey) + sshKey = key.key + except: + sshKey = None + + + owner = Administrator.objects.get(userName=vpsOwner) + package = Package.objects.get(packageName=vpsPackage) + ip = IPAddresses.objects.get(ipAddr=vpsIP) + + ## Some checks + + if ip.used == 1: + logging.CyberCPLogFileWriter.statusWriter(data['tempStatusPath'], 'This IP is already in use. [404]') + return 0, 'This IP is already in use.' + + if VPS.objects.filter(hostName=hostname).count() > 0: + logging.CyberCPLogFileWriter.statusWriter(data['tempStatusPath'], 'Hostname is already taken. [404]') + return 0, 'Hostname is already taken.' + + logging.CyberCPLogFileWriter.statusWriter(data['tempStatusPath'], 'Starting to create virtual machine..,10') + + logger.operationsLog('Starting to create virtual machine: ' + vpsIP, 'Info', stack()[0][3]) + + ## + + uploadSource = self.setupNetworkingFiles(vpsIP, osName, ip.pool, hostname, data['tempStatusPath']) + + ## + + logging.CyberCPLogFileWriter.statusWriter(data['tempStatusPath'], + 'Creating virtual machine disk..,20') + + if self.setupVMDisk(hostname, osName, uploadSource, rootPassword, package, data['tempStatusPath'], sshKey) == 0: + logging.CyberCPLogFileWriter.statusWriter(data['tempStatusPath'], 'Failed to setup virtual machine disk. [404]') + return 0 + + logging.CyberCPLogFileWriter.statusWriter(data['tempStatusPath'], + 'Booting virtual machine..,80') + + ## Server IP + + ipFile = "/etc/cyberpanel/machineIP" + f = open(ipFile) + ipData = f.read() + vncHost = ipData.split('\n', 1)[0] + + ## Finding VNC Port + if VPS.objects.count() == 0: + vncPort = 5900 + webSocketPort = 0 + else: + vncPort = VPS.objects.all().aggregate(Max('vncPort'))['vncPort__max'] + 1 + webSocketPort = VPS.objects.count() + + vncPassword = randomPassword.generate_pass(50) + + if self.bootVirtualMachine(package, hostname, vncHost, str(vncPort), vncPassword, str(webSocketPort), hostname, 'virbr0', data['tempStatusPath']) == 0: + logging.CyberCPLogFileWriter.statusWriter(data['tempStatusPath'], 'Failed to boot virtual machine. [404]') + return 0 + + ## Saving VM To database + + newVPS = VPS(owner=owner, ipAddr=ip, package=package, hostName=hostname, networkSpeed=networkSpeed, + vncPort=vncPort, vncPassword=vncPassword, websocketPort=webSocketPort) + newVPS.save() + ip.used = 1 + ip.save() + + ## Installing network limitations + + ## Reading interface name + + interfaceFile = "/etc/cyberpanel/interfaceName" + f = open(interfaceFile) + interfaceData = f.read() + interfaceName = interfaceData.split('\n', 1)[0] + + virtualMachineAPI.limitVMSpeed(str(newVPS.id), vpsIP, 'virbr0', networkSpeed) + logging.CyberCPLogFileWriter.statusWriter(data['tempStatusPath'], 'Virtual Machine successfully created.. [200]') + + logger.operationsLog('Virtual machine ' + vpsIP + ' successfully created.', 'Success', stack()[0][3]) + + return 1 + + except BaseException, msg: + if logLevel.debug == True: + logger.operationsLog(str(msg), "Error", stack()[0][3]) + logger.writeToFile(str(msg), "Error", stack()[0][3]) + logging.CyberCPLogFileWriter.statusWriter(data['tempStatusPath'], str(msg) + ' [404]') + return 0 + diff --git a/CyberTronAPI/hashPassword.py b/CyberTronAPI/hashPassword.py new file mode 100755 index 000000000..b360186fe --- /dev/null +++ b/CyberTronAPI/hashPassword.py @@ -0,0 +1,13 @@ +import uuid +import hashlib + + +def hash_password(password): + # uuid is used to generate a random number + salt = uuid.uuid4().hex + return hashlib.sha256(salt.encode() + password.encode()).hexdigest() + ':' + salt + + +def check_password(hashed_password, user_password): + password, salt = hashed_password.split(':') + return password == hashlib.sha256(salt.encode() + user_password.encode()).hexdigest() \ No newline at end of file diff --git a/CyberTronAPI/logLevel.py b/CyberTronAPI/logLevel.py new file mode 100755 index 000000000..dc9ac62f8 --- /dev/null +++ b/CyberTronAPI/logLevel.py @@ -0,0 +1,2 @@ +class logLevel: + debug = False \ No newline at end of file diff --git a/CyberTronAPI/randomPassword.py b/CyberTronAPI/randomPassword.py new file mode 100755 index 000000000..2eb292e45 --- /dev/null +++ b/CyberTronAPI/randomPassword.py @@ -0,0 +1,38 @@ +from os import urandom +from random import choice + +char_set = {'small': 'abcdefghijklmnopqrstuvwxyz', + 'nums': '0123456789', + 'big': 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', + } + + +def generate_pass(length=14): + """Function to generate a password""" + + password = [] + + while len(password) < length: + key = choice(char_set.keys()) + a_char = urandom(1) + if a_char in char_set[key]: + if check_prev_char(password, char_set[key]): + continue + else: + password.append(a_char) + return ''.join(password) + + +def check_prev_char(password, current_char_set): + """Function to ensure that there are no consecutive + UPPERCASE/lowercase/numbers/special-characters.""" + + index = len(password) + if index == 0: + return False + else: + prev_char = password[index - 1] + if prev_char in current_char_set: + return True + else: + return False \ No newline at end of file diff --git a/CyberTronAPI/sslUtilities.py b/CyberTronAPI/sslUtilities.py new file mode 100755 index 000000000..bae2d6830 --- /dev/null +++ b/CyberTronAPI/sslUtilities.py @@ -0,0 +1,341 @@ +import CyberCPLogFileWriter as logging +import shutil +import os +import shlex +import subprocess +import socket + +class sslUtilities: + + Server_root = "/usr/local/lsws" + + @staticmethod + def checkIfSSLMap(virtualHostName): + try: + data = open("/usr/local/lsws/conf/httpd_config.conf").readlines() + + sslCheck = 0 + + for items in data: + if items.find("listener") >-1 and items.find("SSL") > -1: + sslCheck = 1 + continue + if sslCheck == 1: + if items.find("}") > -1: + return 0 + if items.find(virtualHostName) > -1 and sslCheck == 1: + data = filter(None, items.split(" ")) + if data[1] == virtualHostName: + return 1 + + except BaseException,msg: + logging.CyberCPLogFileWriter.writeToFile(str(msg) + " [IO Error with main config file [checkIfSSLMap]]") + return 0 + + + @staticmethod + def installSSLForDomain(virtualHostName): + + + pathToStoreSSL = sslUtilities.Server_root + "/conf/vhosts/" + "SSL-" + virtualHostName + + confPath = sslUtilities.Server_root + "/conf/vhosts/" + virtualHostName + completePathToConfigFile = confPath + "/vhost.conf" + + try: + map = " map " + virtualHostName + " " + virtualHostName + "\n" + + if sslUtilities.checkSSLListener()!=1: + + writeDataToFile = open("/usr/local/lsws/conf/httpd_config.conf", 'a') + + listener = "listener SSL {" + "\n" + address = " address *:443" + "\n" + secure = " secure 1" + "\n" + keyFile = " keyFile " + pathToStoreSSL + "/privkey.pem" + "\n" + certFile = " certFile " + pathToStoreSSL + "/fullchain.pem" + "\n" + certChain = " certChain 1" + "\n" + sslProtocol = " sslProtocol 30" + "\n" + map = " map " + virtualHostName + " " + virtualHostName + "\n" + final = "}" + "\n" + "\n" + + writeDataToFile.writelines("\n") + writeDataToFile.writelines(listener) + writeDataToFile.writelines(address) + writeDataToFile.writelines(secure) + writeDataToFile.writelines(keyFile) + writeDataToFile.writelines(certFile) + writeDataToFile.writelines(certChain) + writeDataToFile.writelines(sslProtocol) + writeDataToFile.writelines(map) + writeDataToFile.writelines(final) + writeDataToFile.writelines("\n") + writeDataToFile.close() + + + else: + + if sslUtilities.checkIfSSLMap(virtualHostName) == 0: + + data = open("/usr/local/lsws/conf/httpd_config.conf").readlines() + writeDataToFile = open("/usr/local/lsws/conf/httpd_config.conf", 'w') + sslCheck = 0 + + for items in data: + if items.find("listener")>-1 and items.find("SSL") > -1: + sslCheck = 1 + + if (sslCheck == 1): + writeDataToFile.writelines(items) + writeDataToFile.writelines(map) + sslCheck = 0 + else: + writeDataToFile.writelines(items) + writeDataToFile.close() + + ###################### Write per host Configs for SSL ################### + + data = open(completePathToConfigFile,"r").readlines() + + ## check if vhssl is already in vhconf file + + vhsslPresense = 0 + + for items in data: + if items.find("vhssl")>-1: + vhsslPresense = 1 + + + if vhsslPresense == 0: + writeSSLConfig = open(completePathToConfigFile,"a") + + vhssl = "vhssl {" + "\n" + keyFile = " keyFile " + pathToStoreSSL + "/privkey.pem" + "\n" + certFile = " certFile " + pathToStoreSSL + "/fullchain.pem" + "\n" + certChain = " certChain 1" + "\n" + sslProtocol = " sslProtocol 30" + "\n" + final = "}" + + writeSSLConfig.writelines("\n") + + writeSSLConfig.writelines(vhssl) + writeSSLConfig.writelines(keyFile) + writeSSLConfig.writelines(certFile) + writeSSLConfig.writelines(certChain) + writeSSLConfig.writelines(sslProtocol) + writeSSLConfig.writelines(final) + + + writeSSLConfig.writelines("\n") + + writeSSLConfig.close() + + return 1 + + except BaseException,msg: + logging.CyberCPLogFileWriter.writeToFile(str(msg) + " [installSSLForDomain]]") + return 0 + + + @staticmethod + def checkSSLListener(): + try: + data = open("/usr/local/lsws/conf/httpd_config.conf").readlines() + for items in data: + if items.find("listener SSL") > -1: + return 1 + + except BaseException,msg: + logging.CyberCPLogFileWriter.writeToFile(str(msg) + " [IO Error with main config file [checkSSLListener]]") + return str(msg) + return 0 + + @staticmethod + def getDNSRecords(virtualHostName): + try: + + withoutWWW = socket.gethostbyname(virtualHostName) + withWWW = socket.gethostbyname('www.' + virtualHostName) + + return [1, withWWW, withoutWWW] + + except BaseException, msg: + return [0, "347 " + str(msg) + " [issueSSLForDomain]"] + + + @staticmethod + def obtainSSLForADomain(virtualHostName,adminEmail,sslpath, aliasDomain = None): + try: + + ## Obtaining Server IP + + ipFile = "/etc/cyberpanel/machineIP" + f = open(ipFile) + ipData = f.read() + serverIPAddress = ipData.split('\n', 1)[0] + + ## Obtaining Domain IPs + + if aliasDomain == None: + + ipRecords = sslUtilities.getDNSRecords(virtualHostName) + + + if ipRecords[0] == 1: + + if serverIPAddress == ipRecords[1] and serverIPAddress == ipRecords[2]: + command = "certbot certonly -n --expand --agree-tos --email " + adminEmail + " --webroot -w " + sslpath + " -d " + virtualHostName + " -d www." + virtualHostName + logging.CyberCPLogFileWriter.writeToFile( + "SSL successfully issued for domain : " + virtualHostName + " and www." + virtualHostName) + else: + if serverIPAddress == ipRecords[2]: + command = "certbot certonly -n --agree-tos --email " + adminEmail + " --webroot -w " + sslpath + " -d " + virtualHostName + logging.CyberCPLogFileWriter.writeToFile( + "SSL is issued without 'www' due to DNS error for domain : " + virtualHostName) + else: + logging.CyberCPLogFileWriter.writeToFile( + "DNS Records for " + virtualHostName + " does not point to this server, issuing self signed certificate.") + return 0 + else: + logging.CyberCPLogFileWriter.writeToFile( + "Failed to obtain DNS records for " + virtualHostName + ", issuing self signed certificate.") + return 0 + + else: + + ipRecords = sslUtilities.getDNSRecords(virtualHostName) + + if ipRecords[0] == 1: + + if serverIPAddress == ipRecords[1] and serverIPAddress == ipRecords[2]: + + ipRecordsAlias = sslUtilities.getDNSRecords(aliasDomain) + + if serverIPAddress == ipRecordsAlias[1] and serverIPAddress == ipRecordsAlias[2]: + + command = "certbot certonly -n --expand --agree-tos --email " + adminEmail + " --webroot -w " + sslpath + " -d " + virtualHostName + " -d www." + virtualHostName + " -d " + aliasDomain + " -d www." + aliasDomain + + else: + if serverIPAddress == ipRecordsAlias[2]: + command = "certbot certonly -n --expand --agree-tos --email " + adminEmail + " --webroot -w " + sslpath + " -d " + virtualHostName + " -d www." + virtualHostName + " -d " + aliasDomain + else: + command = "certbot certonly -n --expand --agree-tos --email " + adminEmail + " --webroot -w " + sslpath + " -d " + virtualHostName + " -d www." + virtualHostName + + else: + if serverIPAddress == ipRecords[2]: + + ipRecordsAlias = sslUtilities.getDNSRecords(aliasDomain) + + if serverIPAddress == ipRecordsAlias[1] and serverIPAddress == ipRecordsAlias[2]: + + command = "certbot certonly -n --expand --agree-tos --email " + adminEmail + " --webroot -w " + sslpath + " -d " + virtualHostName + " -d " + aliasDomain + " -d www." + aliasDomain + + else: + if serverIPAddress == ipRecordsAlias[2]: + command = "certbot certonly -n --expand --agree-tos --email " + adminEmail + " --webroot -w " + sslpath + " -d " + virtualHostName + " -d " + aliasDomain + else: + command = "certbot certonly -n --expand --agree-tos --email " + adminEmail + " --webroot -w " + sslpath + " -d " + virtualHostName + + logging.CyberCPLogFileWriter.writeToFile( + "SSL is issued without 'www' due to DNS error for domain : " + virtualHostName) + else: + + ipRecordsAlias = sslUtilities.getDNSRecords(aliasDomain) + + if serverIPAddress == ipRecordsAlias[1] and serverIPAddress == ipRecordsAlias[2]: + command = "certbot certonly -n --expand --agree-tos --email " + adminEmail + " --webroot -w " + sslpath + " -d " + aliasDomain + " -d www." + aliasDomain + else: + if serverIPAddress == ipRecordsAlias[2]: + command = "certbot certonly -n --expand --agree-tos --email " + adminEmail + " --webroot -w " + sslpath + " -d " + aliasDomain + else: + return 0 + else: + logging.CyberCPLogFileWriter.writeToFile( + "Failed to obtain DNS records for " + virtualHostName + ", issuing self signed certificate.") + return 0 + + ## SSL Paths + + + pathToStoreSSL = sslUtilities.Server_root + "/conf/vhosts/" + "SSL-" + virtualHostName + + if not os.path.exists(pathToStoreSSL): + os.mkdir(pathToStoreSSL) + + pathToStoreSSLPrivKey = pathToStoreSSL + "/privkey.pem" + pathToStoreSSLFullChain = pathToStoreSSL + "/fullchain.pem" + + + ## + + output = subprocess.check_output(shlex.split(command)) + + data = output.split('\n') + + if output.find('Congratulations!') > -1: + + ###### Copy SSL To config location ###### + + + for items in data: + if items.find(virtualHostName) > -1 and items.find('fullchain.pem') > -1: + srcFullChain = items.strip(' ') + elif items.find(virtualHostName) > -1 and items.find('privkey.pem') > -1: + srcPrivKey = items.strip(' ') + + + if os.path.exists(pathToStoreSSLPrivKey): + os.remove(pathToStoreSSLPrivKey) + if os.path.exists(pathToStoreSSLFullChain): + os.remove(pathToStoreSSLFullChain) + + shutil.copy(srcPrivKey, pathToStoreSSLPrivKey) + shutil.copy(srcFullChain, pathToStoreSSLFullChain) + + return 1 + + elif output.find('no action taken.') > -1: + return 1 + elif output.find('Failed authorization procedure') > -1: + logging.CyberCPLogFileWriter.writeToFile('Failed authorization procedure for ' + virtualHostName + " while issuing Let's Encrypt SSL.") + return 0 + elif output.find('Too many SSL requests for this domain, please try to get SSL at later time.') > -1: + logging.CyberCPLogFileWriter.writeToFile( + 'Too many SSL requests for ' + virtualHostName + " please try to get SSL at later time.") + return 0 + + except BaseException,msg: + logging.CyberCPLogFileWriter.writeToFile(str(msg) + " [Failed to obtain SSL. [obtainSSLForADomain]]") + return 0 + + +def issueSSLForDomain(domain,adminEmail,sslpath, aliasDomain = None): + try: + + if sslUtilities.obtainSSLForADomain(domain, adminEmail, sslpath, aliasDomain) == 1: + + if sslUtilities.installSSLForDomain(domain) == 1: + return [1, "None"] + else: + return [0, "210 Failed to install SSL for domain. [issueSSLForDomain]"] + else: + pathToStoreSSL = sslUtilities.Server_root + "/conf/vhosts/" + "SSL-" + domain + + if not os.path.exists(pathToStoreSSL): + os.mkdir(pathToStoreSSL) + + pathToStoreSSLPrivKey = pathToStoreSSL + "/privkey.pem" + pathToStoreSSLFullChain = pathToStoreSSL + "/fullchain.pem" + + command = 'openssl req -newkey rsa:2048 -new -nodes -x509 -days 3650 -subj "/C=US/ST=Denial/L=Springfield/O=Dis/CN=www.example.com" -keyout ' + pathToStoreSSLPrivKey + ' -out ' + pathToStoreSSLFullChain + cmd = shlex.split(command) + subprocess.call(cmd) + + if sslUtilities.installSSLForDomain(domain) == 1: + logging.CyberCPLogFileWriter.writeToFile("Self signed SSL issued for " + domain + ".") + return [1, "None"] + else: + return [0, "220 Failed to install SSL for domain. [issueSSLForDomain]"] + + except BaseException,msg: + return [0, "347 "+ str(msg)+ " [issueSSLForDomain]"] diff --git a/CyberTronAPI/test.py b/CyberTronAPI/test.py new file mode 100755 index 000000000..3cdf320f0 --- /dev/null +++ b/CyberTronAPI/test.py @@ -0,0 +1,29 @@ +#!/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 CyberTronLogger import CyberTronLogger as logger +from inspect import stack +from shlex import split +from subprocess import call,CalledProcessError +from os.path import join +from random import randint +from logLevel import logLevel +from ipManagement.models import IPAddresses +from packages.models import VMPackage as Package +from django.db.models import Max +import CyberTronAPI.randomPassword as randomPassword +from vpsManagement.models import VPS +from loginSystem.models import Administrator +from CyberTronAPI.virtualMachineAPIKVM import virtualMachineAPI + + +def setupVMDisk(): + + command = 'sudo virt-builder centos-7.2 -o /var/lib/libvirt/images/199.241.188.139.qcow2 --size 100G --root-password password:9xvps --upload /home/cyberpanel/ifcfg-ens384536:/etc/sysconfig/network-scripts/ifcfg-eth0 --upload /home/cyberpanel/network_62835:/etc/sysconfig/network --upload /home/cyberpanel/resolv_80440:/etc/resolv.conf' + result = call(split(command)) + +setupVMDisk() \ No newline at end of file diff --git a/CyberTronAPI/virtualMachineAPI.py b/CyberTronAPI/virtualMachineAPI.py new file mode 100755 index 000000000..a87afba35 --- /dev/null +++ b/CyberTronAPI/virtualMachineAPI.py @@ -0,0 +1,638 @@ +from CyberTronLogger import CyberTronLogger as logger +from inspect import stack +from shlex import split +from subprocess import call,CalledProcessError +from os.path import join +from os import remove +from random import randint +from shutil import move +import libvirt +from logLevel import logLevel + +class virtualMachineAPI: + + ## os.path.join + templatesPath = join('/var','lib','libvirt','templates') + imagesPath = join('/var','lib','libvirt','images') + + + @staticmethod + def setupNetworkingFiles(vmName, osName, ipAddress, netmask, gateway, hostName): + try: + + if logLevel.debug == True: + logger.operationsLog('Setting up network for: ' + vmName + '.', 'Debug', stack()[0][3]) + + uploadSource = [] + + if osName.find("centos") > -1: + ###### /etc/sysconfig/network-scripts/ifcfg-eth0 + + eth0 = "ifcfg-eth0_" + str(randint(10000, 99999)) + eth0File = open(eth0, 'w') + + eth0File.writelines('DEVICE="eth0"\n') + eth0File.writelines('NM_CONTROLLED="yes"\n') + eth0File.writelines('ONBOOT=yes\n') + eth0File.writelines('TYPE=Ethernet\n') + eth0File.writelines('BOOTPROTO=static\n') + eth0File.writelines('NAME="System eth0"\n') + eth0File.writelines('IPADDR=' + ipAddress + '\n') + eth0File.writelines('NETMASK=' + netmask + '\n') + + eth0File.close() + + uploadSource.append(eth0) + + ###### /etc/sysconfig/network + + network = "network_" + str(randint(10000, 99999) + 1) + networkFile = open(network, 'w') + + networkFile.writelines('NETWORKING=yes\n') + networkFile.writelines('HOSTNAME=' + hostName + '\n') + networkFile.writelines('GATEWAY=' + gateway + '\n') + + networkFile.close() + + uploadSource.append(network) + + ###### /etc/resolv.conf + + resolv = "resolv_" + str(randint(10000, 99999) + 2) + resolvFile = open(resolv, 'w') + + resolvFile.writelines("nameserver 8.8.8.8\n") + + resolvFile.close() + + uploadSource.append(resolv) + elif osName.find("debian") > -1 or osName.find("ubuntu") > -1: + + ###### /etc/network/interfaces + + eth0 = "interfaces_" + str(randint(10000, 99999)) + eth0File = open(eth0, 'w') + + eth0File.writelines('# This file describes the network interfaces available on your system\n') + eth0File.writelines('# and how to activate them. For more information, see interfaces(5).\n') + + eth0File.writelines('\n') + + eth0File.writelines('# The loopback network interface\n') + eth0File.writelines('auto lo\n') + eth0File.writelines('iface lo inet loopback\n') + + eth0File.writelines('\n') + + ## To deal with Debian 9.3 and ubuntu 16.04 issue. + + eth0File.writelines('# The primary network interface\n') + + if osName == "debian-9.3.x64" or osName == "ubuntu-16.04.x32" or osName == "ubuntu-16.04.x64" or osName == "ubuntu-17.10.x64": + eth0File.writelines('allow-hotplug ens3\n') + eth0File.writelines('iface ens3 inet static\n') + else: + eth0File.writelines('allow-hotplug eth0\n') + eth0File.writelines('iface eth0 inet static\n') + + eth0File.writelines(' address '+ipAddress+'\n') + eth0File.writelines(' netmask ' + netmask +'\n') + eth0File.writelines(' gateway ' + gateway + '\n') + eth0File.writelines('# dns-* options are implemented by the resolvconf package, if installed\n') + eth0File.writelines('dns-nameservers 8.8.8.8\n') + eth0File.writelines('dns-search com\n') + + eth0File.close() + + uploadSource.append(eth0) + elif osName.find("fedora") > -1: + + ###### /etc/sysconfig/network-scripts/ifcfg-ens3 + + eth0 = "interfaces_" + str(randint(10000, 99999)) + eth0File = open(eth0, 'w') + + eth0File.writelines('TYPE=Ethernet\n') + eth0File.writelines('PROXY_METHOD=none\n') + + + eth0File.writelines('BROWSER_ONLY=no\n') + eth0File.writelines('BOOTPROTO=none\n') + eth0File.writelines('DEFROUTE=yes\n') + + + eth0File.writelines('IPV4_FAILURE_FATAL=no\n') + eth0File.writelines('IPV6INIT=yes\n') + eth0File.writelines('IPV6_AUTOCONF=yes\n') + + eth0File.writelines('IPV6_DEFROUTE=yes\n') + eth0File.writelines('IPV6_FAILURE_FATAL=no\n') + eth0File.writelines('IPV6_ADDR_GEN_MODE=stable-privacy\n') + eth0File.writelines('NAME=ens3\n') + eth0File.writelines('ONBOOT=yes\n') + eth0File.writelines('AUTOCONNECT_PRIORITY=-999\n') + + eth0File.writelines('DEVICE=ens3\n') + eth0File.writelines('IPADDR=' + ipAddress + '\n') + eth0File.writelines('NETMASK=' + netmask + '\n') + eth0File.writelines('GATEWAY=' + gateway + '\n') + eth0File.writelines('DNS1=8.8.8.8\n') + eth0File.writelines('IPV6_PRIVACY=no\n') + + eth0File.close() + uploadSource.append(eth0) + elif osName.find("freebsd") > -1: + + ###### /etc/rc.conf + + eth0 = "ifcfg-eth0_" + str(randint(10000, 99999)) + eth0File = open(eth0, 'w') + + eth0File.writelines('DEVICE="eth0"\n') + eth0File.writelines('NM_CONTROLLED="yes"\n') + eth0File.writelines('ONBOOT=yes\n') + eth0File.writelines('TYPE=Ethernet\n') + eth0File.writelines('BOOTPROTO=static\n') + eth0File.writelines('NAME="System eth0"\n') + eth0File.writelines('IPADDR=' + ipAddress + '\n') + eth0File.writelines('NETMASK=' + netmask + '\n') + + eth0File.close() + + uploadSource.append(eth0) + + if logLevel.debug == True: + logger.operationsLog('Network settings installed for: ' + vmName + '.', 'Debug', stack()[0][3]) + + return uploadSource + + except BaseException, msg: + if logLevel.debug == True: + logger.operationsLog(str(msg), "Error", stack()[0][3]) + logger.writeToFile(str(msg), "Error", stack()[0][3]) + return 0 + + ''' + vmName = Usually IP Address. + osName = Examples operatingSystem-X.xx.x86 + uploadSource = An array containing complete path of files to be uploaded to the image after creation. + rootPassword = Virtual Machine root password. + ''' + + @staticmethod + def setupVMDisk(vmName, osName, size, uploadSource, rootPassword): + try: + + if logLevel.debug == True: + logger.operationsLog('Creating disk image for: ' + vmName + '.', 'Debug', stack()[0][3]) + + sourcePath = join(virtualMachineAPI.templatesPath,osName+".qcow2") + tempPath = join(virtualMachineAPI.imagesPath,vmName+"-temp.qcow2") + finalPath = join(virtualMachineAPI.imagesPath,vmName+".qcow2") + + ## Build upload command + + uploadCommand = "" + + if osName.find('centos') > -1: + uploadCommand = " --upload " + uploadSource[0] + ":" + "/etc/sysconfig/network-scripts/ifcfg-eth0" + uploadCommand = uploadCommand + " --upload " + uploadSource[1] + ":" + "/etc/sysconfig/network" + uploadCommand = uploadCommand + " --upload " + uploadSource[2] + ":" + "/etc/resolv.conf" + elif osName.find('debian') > -1: + uploadCommand = " --upload " + uploadSource[0] + ":" + "/etc/network/interfaces" + " --firstboot-command 'apt-get purge openssh-server -y' --firstboot-command 'apt-get install openssh-server -y'" + elif osName.find('ubuntu') > -1: + uploadCommand = " --upload " + uploadSource[0] + ":" + "/etc/network/interfaces" + " --firstboot-command 'apt-get remove openssh-server -y' --firstboot-command 'apt-get install openssh-server -y'" + elif osName.find('fedora') > -1: + uploadCommand = " --upload " + uploadSource[0] + ":" + "/etc/sysconfig/network-scripts/ifcfg-ens3" + " --firstboot-command 'yum erase openssh-server -y' --firstboot-command 'yum install openssh-server -y'" + + ## Creating temporary disk image. + + command = "qemu-img create -b " + sourcePath + " -f qcow2 " + tempPath + result = call(split(command)) + + if result == 1: + raise CalledProcessError + + if logLevel.debug == True: + logger.operationsLog("Temporary image created for: " + vmName + ".", "Debug", stack()[0][3]) + + ## Checking size, if less or = 3GB, no need to resize. + + if int(size) <= 3: + move(tempPath, finalPath) + + if logLevel.debug == True: + logger.operationsLog("Image successfully prepared for: " + vmName + ".", "Debug", stack()[0][3]) + + else: + + command = "qemu-img create -f qcow2 " + finalPath + " " + size + "G" + result = call(split(command)) + + if result == 1: + raise CalledProcessError + + if logLevel.debug == True: + logger.operationsLog("Created resized final image for: " + vmName + ".", "Debug", stack()[0][3]) + + if osName == "centos-7.4.x64": + + command = "virt-resize --expand /dev/sda2 --lv-expand /dev/centos/root " + tempPath + " " + finalPath + result = call(split(command)) + + + if result == 1: + remove(tempPath) + raise CalledProcessError + else: + remove(tempPath) + + if logLevel.debug == True: + logger.operationsLog("Disk resized and ready to use for: " + vmName + ".", "Debug", + stack()[0][3]) + elif osName == "centos-6.9.x64" or osName == "centos-6.9.x32": + + command = "virt-resize --expand /dev/sda2 --lv-expand /dev/VolGroup/lv_root " + tempPath + " " + finalPath + result = call(split(command)) + + if result == 1: + remove(tempPath) + raise CalledProcessError + else: + remove(tempPath) + + if logLevel.debug == True: + logger.operationsLog("Disk resized and ready to use for: " + vmName + ".", "Debug", + stack()[0][3]) + elif osName == "debian-7.11.x32" or osName == "debian-7.11.x64": + + command = "virt-resize --expand /dev/sda1 --lv-expand /dev/debian/root " + tempPath + " " + finalPath + result = call(split(command)) + + if result == 1: + remove(tempPath) + raise CalledProcessError + else: + remove(tempPath) + + if logLevel.debug == True: + logger.operationsLog("Disk resized and ready to use for: " + vmName + ".", "Debug", + stack()[0][3]) + elif osName == "debian-8.10.x32" or osName == "debian-8.10.x64" or osName == "debian-9.3.x64": + command = "virt-resize --expand /dev/sda2 --lv-expand /dev/debian/root " + tempPath + " " + finalPath + result = call(split(command)) + + if result == 1: + remove(tempPath) + raise CalledProcessError + else: + remove(tempPath) + + if logLevel.debug == True: + logger.operationsLog("Disk resized and ready to use for: " + vmName + ".", "Debug", + stack()[0][3]) + elif osName == "fedora-27.x64" or osName == "fedora-26.x64": + command = "virt-resize --expand /dev/sda2 --lv-expand /dev/fedora/root " + tempPath + " " + finalPath + result = call(split(command)) + + if result == 1: + remove(tempPath) + raise CalledProcessError + else: + remove(tempPath) + + if logLevel.debug == True: + logger.operationsLog("Disk resized and ready to use for: " + vmName + ".", "Debug", + stack()[0][3]) + elif osName == "ubuntu-14.04.x32" or osName == "ubuntu-14.04.x64" or osName == "ubuntu-16.04.x32" or osName == "ubuntu-16.04.x64" or osName == "ubuntu-17.10.x64": + command = "virt-resize --expand /dev/sda2 --lv-expand /dev/ubuntu/root " + tempPath + " " + finalPath + result = call(split(command)) + + if result == 1: + remove(tempPath) + raise CalledProcessError + else: + remove(tempPath) + + if logLevel.debug == True: + logger.operationsLog("Disk resized and ready to use for: " + vmName + ".", "Debug", + stack()[0][3]) + + + ## Setup network and customize root password + + command = "virt-customize -a " + finalPath + " --root-password password:" + rootPassword + uploadCommand + call(split(command)) + + if result == 1: + raise CalledProcessError + + if logLevel.debug == True: + logger.operationsLog("Root password and network configured for: " + vmName + ".", "Debug", + stack()[0][3]) + return 1 + + return 1 + + except BaseException,msg: + if logLevel.debug == True: + logger.operationsLog(str(msg), "Error", stack()[0][3]) + logger.writeToFile(str(msg), "Error", stack()[0][3]) + return 0 + except CalledProcessError,msg: + if logLevel.debug == True: + logger.operationsLog(str(msg), "Error", stack()[0][3]) + logger.writeToFile(str(msg), "Error", stack()[0][3]) + return 0 + + + """ + Function to create Virtual Machine Disk, which can than be used to create virtual machine. + + vmName = Name of vps, this will be combined with imgDestination and format. + osName = Name of OS, with which this image should be created. + vmDestination = Destination on disk where this image should be placed. + size = Size in GBs. + format = Examples, qcow2, img, qcow, recommend is qcow2. + uploadSource = An array containing complete path of files to be uploaded to the image after creation. + debug = Enable or disable extended debug logging. Defaults to false. + + """ + + @staticmethod + def createVirtualMachineDisk(vmName, osName , vmDestination, size, format, uploadSource): + try: + + if logLevel.debug == True: + logger.operationsLog('Creating disk image for: ' + vmName + '.', 'Debug', stack()[0][3]) + + ## Build upload command + + uploadCommand = "" + + if osName.find('centos') > -1: + uploadCommand = " --upload " + uploadSource[0] + ":" + "/etc/sysconfig/network-scripts/ifcfg-eth0" + uploadCommand = uploadCommand + " --upload " + uploadSource[1] + ":" + "/etc/sysconfig/network" + uploadCommand = uploadCommand + " --upload " + uploadSource[2] + ":" + "/etc/resolv.conf" + + ## Final Image Location -- finalImageLocation = /var/lib/libvirt/192.168.100.1.qcow2 + + finalImageLocation = join(vmDestination, vmName + "." + format) + + ## "virt-builder centos-7.1 -o /var/lib/libvirt/images192.168.100.1.qcow2 --size 50G --format qcow2 --upload ifcfg-eth0:/etc/sysconfig/network-scripts/ --upload network:/etc/sysconfig + + command = "virt-builder " + osName + " -o " + finalImageLocation + " --size " + size + " --format " + format + uploadCommand + result = call(split(command)) + + if result == 1: + raise CalledProcessError + + if logLevel.debug == True: + logger.operationsLog("Disk image created for: " + vmName + ".", "Debug", stack()[0][3]) + + ## Remove temporary generated files + + #for tempFiles in uploadSource: + #remove(tempFiles) + + return 1 + + except BaseException,msg: + if logLevel.debug == True: + logger.writeToFile(str(msg), "Error", stack()[0][3]) + return 0 + except CalledProcessError,msg: + if logLevel.debug == True: + logger.writeToFile(str(msg), "Error", stack()[0][3]) + return 0 + + """ + vmName = Name of the virtual machine, usually the IP Address. + vmRam = Ram to be assigned to this virtual machine. + vmVCPUs = Virtual CPUs to be assigned to this virtual machine. + vmDestination = Path where VM image will be housed. + format = Examples, qcow2, img, qcow, recommend is qcow2. + vncPort = VNC Port for this virtual machine. + osType = OS Type e.g. linux,windows. + osVariant = OS Variant e.g. centos 6, centos 7. + bridgeName = Bridge name to which the interface of this VM will be attached. + debug = Enable or disable extended debug logging. Defaults to false. + + """ + + @staticmethod + def bootVirtualMachine(vmName, vmRam, vmVCPUs, vncHost, vncPort, osType, osVariant, bridgeName): + try: + + if logLevel.debug == True: + logger.operationsLog('Booting: ' + vmName + '.','Debug',stack()[0][3]) + + + finalImageLocation = join(virtualMachineAPI.imagesPath,vmName+".qcow2") + + # virt-install --name 109.238.12.214 --ram 2048 --vcpus=1 --disk 109.238.12.214.qcow2 --graphics vnc,listen=localhost,port=5500 --noautoconsole --hvm --import --os-type=linux --os-variant=rhel7 --network bridge=virbr0 + + command = "virt-install --name " + vmName + " --ram " + vmRam + " --vcpu " + vmVCPUs + " --disk " + \ + finalImageLocation + " --graphics vnc,listen=" +vncHost + ",port=" + vncPort + \ + " --noautoconsole --hvm --import --autostart --os-type=" + osType + " --os-variant=" + \ + osVariant + " --network bridge=" + bridgeName + result = call(split(command)) + + if result == 1: + raise CalledProcessError + + if logLevel.debug == True: + logger.operationsLog("Successfully booted: " + vmName + ".", "Debug", stack()[0][3]) + + return 1 + + except BaseException, msg: + if logLevel.debug == True: + logger.operationsLog(str(msg), "Error", stack()[0][3]) + logger.writeToFile(str(msg), "Error", stack()[0][3]) + return 0 + except CalledProcessError, msg: + if logLevel.debug == True: + logger.operationsLog(str(msg), "Error", stack()[0][3]) + logger.writeToFile(str(msg), "Error", stack()[0][3]) + return 0 + + """ + + + osName = Name of OS, with which this image should be created. + imgDestination = Destination on disk where this image should be placed. + imgName = Name of vps, this will be combined with imgDestination. + size = Size in GBs. + format = Examples, qcow2, img, qcow, recommend is qcow2. + uploadSource = An array containing complete path of files to be uploaded to the image after creation. + UploadDestination = Corressponding array of upload source, defining upload destination of files. + + -- + + vmName = Name of the virtual machine, usually the IP Address. + vmRam = Ram to be assigned to this virtual machine. + vmVCPUs = Virtual CPUs to be assigned to this virtual machine. + diskImage = A complete path to disk image for this virtual machine. + vncPort = VNC Port for this virtual machine. + osType = OS Type e.g. linux,windows. + osVariant = OS Variant e.g. centos 6, centos 7. + bridgeName = Bridge name to which the interface of this VM will be attached. + + """ + + @staticmethod + def createVirtualMachine(vmName, osName, rootPassword, size, vncHost, vmRam, vmVCPUs, vncPort, osType, osVariant, bridgeName, ipAddress, netmask, gateway, hostName): + try: + + logger.operationsLog('Starting to create virtual machine: ' + vmName, 'Info', stack()[0][3]) + + ## + + uploadSource = virtualMachineAPI.setupNetworkingFiles(vmName, osName, ipAddress, netmask, gateway, hostName) + + ## + + if virtualMachineAPI.setupVMDisk(vmName, osName, size, uploadSource, rootPassword) == 0: + return 0 + + ## + + if virtualMachineAPI.bootVirtualMachine(vmName, vmRam, vmVCPUs, vncHost, vncPort, osType, osVariant, bridgeName) == 0: + return 0 + + ## + + logger.operationsLog('Virtual machine ' + vmName + ' successfully created.', 'Success', stack()[0][3]) + + return 1 + + except BaseException, msg: + if logLevel.debug == True: + logger.operationsLog(str(msg), "Error", stack()[0][3]) + logger.writeToFile(str(msg), "Error", stack()[0][3]) + return 0 + + @staticmethod + def deleteVirtualMachine(virtualMachineName): + try: + + obtainStatus, virtualMachine = virtualMachineAPI.obtainVirtualMachineObject(virtualMachineName) + + if obtainStatus == 1: + + if virtualMachine.hasCurrentSnapshot(): + snapShots = virtualMachine.listAllSnapshots() + for snapShot in snapShots: + snapShot.delete() + + if virtualMachine.isActive(): + virtualMachine.destroy() + + virtualMachine.undefine() + + ## Removing virtual machine file. + + try: + pathToImg = join(virtualMachineAPI.imagesPath, virtualMachineName + '.qcow2') + remove(pathToImg) + except BaseException,msg: + if logLevel.debug == True: + logger.operationsLog(str(msg), "Error", stack()[0][3]) + logger.writeToFile(str(msg), "Error", stack()[0][3]) + + ## + + return 1,'No error.' + else: + return 0,'Failed to obtain virtual machine object.' + + except BaseException, msg: + if logLevel.debug == True: + logger.operationsLog(str(msg), "Error", stack()[0][3]) + logger.writeToFile(str(msg), "Error", stack()[0][3]) + return 0, str(msg) + + @staticmethod + def obtainVirtualMachineObject(virtualMachineName): + try: + connection = libvirt.open('qemu:///system') + + if connection == None: + return 0, 'Failed to establish connection.' + + virtualMachine = connection.lookupByName(virtualMachineName) + + if virtualMachine == None: + return 0, 'Can not find virtual machine.' + + return 1,virtualMachine + + + except BaseException, msg: + if logLevel.debug == True: + logger.operationsLog(str(msg), "Error", stack()[0][3]) + logger.writeToFile(str(msg), "Error", stack()[0][3]) + return 0, str(msg) + + @staticmethod + def revertToSnapshot(virtualMachineName, snapshotName): + try: + obtainStatus, virtualMachine = virtualMachineAPI.obtainVirtualMachineObject(virtualMachineName) + + if obtainStatus == 1: + snapshot = virtualMachine.snapshotLookupByName(snapshotName) + virtualMachine.revertToSnapshot(snapshot) + return 1, 'No error.' + else: + return 0,'Failed to obtain virtual machine object.' + except BaseException, msg: + if logLevel.debug == True: + logger.operationsLog(str(msg), "Error", stack()[0][3]) + logger.writeToFile(str(msg), "Error", stack()[0][3]) + return 0, str(msg) + + @staticmethod + def softReboot(virtualMachineName): + try: + obtainStatus, virtualMachine = virtualMachineAPI.obtainVirtualMachineObject(virtualMachineName) + if obtainStatus == 1: + if virtualMachine.reboot(): + return 1, 'No error.' + else: + return 0,'Failed to reboot.' + else: + return 0,'Failed to obtain virtual machine object.' + except BaseException, msg: + if logLevel.debug == True: + logger.operationsLog(str(msg), "Error", stack()[0][3]) + logger.writeToFile(str(msg), "Error", stack()[0][3]) + return 0, str(msg) + + @staticmethod + def hardShutdown(virtualMachineName): + try: + obtainStatus, virtualMachine = virtualMachineAPI.obtainVirtualMachineObject(virtualMachineName) + if obtainStatus == 1: + if virtualMachine.destroy(): + return 1, 'No error.' + else: + return 0,'Failed to shutdown.' + else: + return 0,'Failed to obtain virtual machine object.' + except BaseException, msg: + if logLevel.debug == True: + logger.operationsLog(str(msg), "Error", stack()[0][3]) + logger.writeToFile(str(msg), "Error", stack()[0][3]) + return 0, str(msg) + + + + +virtualMachineAPI.createVirtualMachine('192.111.145.235','centos-7.4.x64',"litespeedtech","50",'192.111.145.234','2048','2','5900','linux','rhel7','virbr0','192.111.145.235','255.255.255.248','192.111.145.233','usman.cybertronproject.com') + +#print virtualMachineAPI.deleteVirtualMachine('109.238.12.214') + +#print virtualMachineAPI.revertToSnapshot('109.238.12.214','CyberPanel') +#virtualMachineAPI.softReboot('109.238.12.214') \ No newline at end of file diff --git a/CyberTronAPI/virtualMachineAPIKVM.py b/CyberTronAPI/virtualMachineAPIKVM.py new file mode 100755 index 000000000..03bd8a5f8 --- /dev/null +++ b/CyberTronAPI/virtualMachineAPIKVM.py @@ -0,0 +1,613 @@ +from CyberTronLogger import CyberTronLogger as logger +from inspect import stack +from shlex import split +from subprocess import call,CalledProcessError +from os.path import join +from os import remove, path +from random import randint +import libvirt +from logLevel import logLevel +from xml.etree import ElementTree + + + +class virtualMachineAPI: + + ## os.path.join + templatesPath = join('/var','lib','libvirt','templates') + imagesPath = join('/var','lib','libvirt','images') + + @staticmethod + def obtainVirtualMachineObject(virtualMachineName): + try: + connection = libvirt.open('qemu:///system') + + if connection == None: + return 0, 'Failed to establish connection.' + + virtualMachine = connection.lookupByName(virtualMachineName) + + if virtualMachine == None: + return 0, 'Can not find virtual machine.' + + return 1, virtualMachine + + + except BaseException, msg: + if logLevel.debug == True: + logger.operationsLog(str(msg), "Error", stack()[0][3]) + logger.writeToFile(str(msg), "Error", stack()[0][3]) + return 0, str(msg) + + @staticmethod + def limitVMSpeed(vpsID, vpsIP, interface, interfaceLimit): + try: + ## Creating class + + command = 'tc class add dev ' + interface + ' parent 2:1 classid ' + '2:' + vpsID + ' htb rate ' + interfaceLimit + logger.writeToFile(command,'Info',stack()[0][3]) + + result = call(split(command)) + + if result == 1: + raise CalledProcessError + else: + pass + + ## Create IP Filter. + + command = 'tc filter add dev ' + interface + ' parent 2:0 protocol ip prio 1 u32 match ip src ' + vpsIP + ' flowid 2:' + vpsID + logger.writeToFile(command,'Info',stack()[0][3]) + result = call(split(command)) + + if result == 1: + raise CalledProcessError + else: + pass + + return 1 + + except BaseException, msg: + if logLevel.debug == True: + logger.operationsLog(str(msg), "Error", stack()[0][3]) + logger.writeToFile(str(msg), "Error", stack()[0][3]) + return 0 + except CalledProcessError, msg: + if logLevel.debug == True: + logger.operationsLog(str(msg), "Error", stack()[0][3]) + logger.writeToFile(str(msg), "Error", stack()[0][3]) + return 0 + + @staticmethod + def removeVMSpeedLimit(vpsID, interface): + try: + ## Removing filter. + + command = 'tc filter del dev ' + interface + ' parent 2:0 protocol ip prio 1 u32 flowid 2:' + vpsID + + result = call(split(command)) + + if result == 1: + raise CalledProcessError + else: + pass + + ## Removing class. + + command = 'tc class del dev ' + interface + ' classid 2:' + vpsID + + result = call(split(command)) + + if result == 1: + raise CalledProcessError + else: + pass + + return 1 + + except BaseException, msg: + if logLevel.debug == True: + logger.operationsLog(str(msg), "Error", stack()[0][3]) + logger.writeToFile(str(msg), "Error", stack()[0][3]) + return 0 + except CalledProcessError, msg: + if logLevel.debug == True: + logger.operationsLog(str(msg), "Error", stack()[0][3]) + logger.writeToFile(str(msg), "Error", stack()[0][3]) + return 0 + + @staticmethod + def deleteVirtualMachine(virtualMachineName): + try: + + obtainStatus, virtualMachine = virtualMachineAPI.obtainVirtualMachineObject(virtualMachineName) + + if obtainStatus == 1: + + if virtualMachine.hasCurrentSnapshot(): + snapShots = virtualMachine.listAllSnapshots() + for snapShot in snapShots: + snapShot.delete() + + if virtualMachine.isActive(): + virtualMachine.destroy() + + virtualMachine.undefine() + + ## Removing virtual machine file. + + try: + pathToImg = join(virtualMachineAPI.imagesPath, virtualMachineName + '.qcow2') + remove(pathToImg) + except BaseException,msg: + if logLevel.debug == True: + logger.operationsLog(str(msg), "Error", stack()[0][3]) + logger.writeToFile(str(msg), "Error", stack()[0][3]) + + ## + + return 1,'No error.' + else: + return 0,'Failed to obtain virtual machine object.' + + except BaseException, msg: + if logLevel.debug == True: + logger.operationsLog(str(msg), "Error", stack()[0][3]) + logger.writeToFile(str(msg), "Error", stack()[0][3]) + return 0, str(msg) + + @staticmethod + def revertToSnapshot(virtualMachineName, snapshotName): + try: + obtainStatus, virtualMachine = virtualMachineAPI.obtainVirtualMachineObject(virtualMachineName) + + if obtainStatus == 1: + snapshot = virtualMachine.snapshotLookupByName(snapshotName) + virtualMachine.revertToSnapshot(snapshot) + return 1, 'No error.' + else: + return 0,'Failed to obtain virtual machine object.' + except BaseException, msg: + if logLevel.debug == True: + logger.operationsLog(str(msg), "Error", stack()[0][3]) + logger.writeToFile(str(msg), "Error", stack()[0][3]) + return 0, str(msg) + + @staticmethod + def softReboot(virtualMachineName): + try: + obtainStatus, virtualMachine = virtualMachineAPI.obtainVirtualMachineObject(virtualMachineName) + if obtainStatus == 1: + if virtualMachine.isActive(): + virtualMachine.reboot() + return 1, 'No error.' + else: + command = 'virsh start ' + virtualMachineName + call(split(command)) + return 1, 'No error.' + else: + return 0,'Failed to obtain virtual machine object.' + except BaseException, msg: + if logLevel.debug == True: + logger.operationsLog(str(msg), "Error", stack()[0][3]) + logger.writeToFile(str(msg), "Error", stack()[0][3]) + return 0, str(msg) + + @staticmethod + def hardShutdown(virtualMachineName): + try: + obtainStatus, virtualMachine = virtualMachineAPI.obtainVirtualMachineObject(virtualMachineName) + if obtainStatus == 1: + if virtualMachine.isActive(): + virtualMachine.destroy() + return 1, 'No error.' + else: + return 0, 'VPS is not running.' + else: + return 0,'Failed to obtain virtual machine object.' + except BaseException, msg: + if logLevel.debug == True: + logger.operationsLog(str(msg), "Error", stack()[0][3]) + logger.writeToFile(str(msg), "Error", stack()[0][3]) + return 0, str(msg) + + @staticmethod + def setupNetworkingFiles(vmName, ipAddress, netmask, gateway, hostName): + try: + + if logLevel.debug == True: + logger.operationsLog('Setting up network for: ' + vmName + '.', 'Debug', stack()[0][3]) + + uploadSource = [] + + ###### /etc/sysconfig/network-scripts/ifcfg-eth0 + + eth0 = "ifcfg-eth0_" + str(randint(10000, 99999)) + eth0File = open(eth0, 'w') + + eth0File.writelines('DEVICE="eth0"\n') + eth0File.writelines('NM_CONTROLLED="yes"\n') + eth0File.writelines('ONBOOT=yes\n') + eth0File.writelines('TYPE=Ethernet\n') + eth0File.writelines('BOOTPROTO=static\n') + eth0File.writelines('NAME="System eth0"\n') + eth0File.writelines('IPADDR=' + ipAddress + '\n') + eth0File.writelines('NETMASK=' + netmask + '\n') + + eth0File.close() + + uploadSource.append(eth0) + + ###### /etc/sysconfig/network + + network = "network_" + str(randint(10000, 99999) + 1) + networkFile = open(network, 'w') + + networkFile.writelines('NETWORKING=yes\n') + networkFile.writelines('HOSTNAME=' + hostName + '\n') + networkFile.writelines('GATEWAY=' + gateway + '\n') + + networkFile.close() + + uploadSource.append(network) + + ###### /etc/resolv.conf + + resolv = "resolv_" + str(randint(10000, 99999) + 2) + resolvFile = open(resolv, 'w') + + resolvFile.writelines("nameserver 8.8.8.8\n") + + resolvFile.close() + + uploadSource.append(resolv) + + if logLevel.debug == True: + logger.operationsLog('Network settings installed for: ' + vmName + '.', 'Debug', stack()[0][3]) + + return uploadSource + + + except BaseException, msg: + if logLevel.debug == True: + logger.operationsLog(str(msg), "Error", stack()[0][3]) + logger.writeToFile(str(msg), "Error", stack()[0][3]) + return 0 + + ''' + vmName = Usually IP Address. + osName = Examples operatingSystem-X.xx.x86 + uploadSource = An array containing complete path of files to be uploaded to the image after creation. + rootPassword = Virtual Machine root password. + ''' + + @staticmethod + def setupVMDisk(vmName, package, uploadSource, rootPassword): + try: + + if logLevel.debug == True: + logger.operationsLog('Creating disk image for: ' + vmName + '.', 'Debug', stack()[0][3]) + + sourcePath = join(virtualMachineAPI.templatesPath, package + ".qcow2") + finalPath = join(virtualMachineAPI.imagesPath, vmName + ".qcow2") + + ## Build upload command + + uploadCommand = "" + + uploadCommand = " --upload " + uploadSource[0] + ":" + "/etc/sysconfig/network-scripts/ifcfg-eth0" + uploadCommand = uploadCommand + " --upload " + uploadSource[1] + ":" + "/etc/sysconfig/network" + uploadCommand = uploadCommand + " --upload " + uploadSource[2] + ":" + "/etc/resolv.conf" + ## Creating temporary disk image. + + command = "qemu-img create -b " + sourcePath + " -f qcow2 " + finalPath + result = call(split(command)) + + if result == 1: + raise CalledProcessError + + if logLevel.debug == True: + logger.operationsLog("Temporary image created for: " + vmName + ".", "Debug", stack()[0][3]) + + ## Setup network and customize root password + + command = "virt-customize -a " + finalPath + " --root-password password:" + rootPassword + uploadCommand + call(split(command)) + + if result == 1: + raise CalledProcessError + + if logLevel.debug == True: + logger.operationsLog("Root password and network configured for: " + vmName + ".", "Debug", + stack()[0][3]) + return 1 + + return 1 + + except BaseException, msg: + if logLevel.debug == True: + logger.operationsLog(str(msg), "Error", stack()[0][3]) + logger.writeToFile(str(msg), "Error", stack()[0][3]) + return 0 + except CalledProcessError, msg: + if logLevel.debug == True: + logger.operationsLog(str(msg), "Error", stack()[0][3]) + logger.writeToFile(str(msg), "Error", stack()[0][3]) + return 0 + + """ + vmName = Name of the virtual machine, usually the IP Address. + vmRam = Ram to be assigned to this virtual machine. + vmVCPUs = Virtual CPUs to be assigned to this virtual machine. + vmDestination = Path where VM image will be housed. + format = Examples, qcow2, img, qcow, recommend is qcow2. + vncPort = VNC Port for this virtual machine. + osType = OS Type e.g. linux,windows. + osVariant = OS Variant e.g. centos 6, centos 7. + bridgeName = Bridge name to which the interface of this VM will be attached. + debug = Enable or disable extended debug logging. Defaults to false. + + """ + + @staticmethod + def bootVirtualMachine(vmName, vmVCPUs, vmRam, vncHost, vncPort, bridgeName, webSocketPort, vncPassword): + try: + + if logLevel.debug == True: + logger.operationsLog('Booting: ' + vmName + '.', 'Debug', stack()[0][3]) + + finalImageLocation = join(virtualMachineAPI.imagesPath, vmName + ".qcow2") + + # virt-install --name 109.238.12.214 --ram 2048 --vcpus=1 --disk 109.238.12.214.qcow2 --graphics vnc,listen=localhost,port=5500 --noautoconsole --hvm --import --os-type=linux --os-variant=rhel7 --network bridge=virbr0 + + command = "virt-install --name " + vmName + " --ram " + vmRam + " --vcpu " + vmVCPUs + " --disk " + \ + finalImageLocation + " --graphics vnc,listen=" + vncHost + ",port=" + vncPort + ",password=" + vncPassword + \ + ' --qemu-commandline=' + '"' + '-vnc :' + webSocketPort + ',websocket' + '"' + \ + " --noautoconsole --hvm --import --autostart --os-type=linux " \ + + "--network bridge=" + bridgeName + logger.writeToFile(command,"Info", stack()[0][3]) + result = call(split(command)) + + if result == 1: + raise CalledProcessError + + if logLevel.debug == True: + logger.operationsLog("Successfully booted: " + vmName + ".", "Debug", stack()[0][3]) + + return 1 + + except BaseException, msg: + if logLevel.debug == True: + logger.operationsLog(str(msg), "Error", stack()[0][3]) + logger.writeToFile(str(msg), "Error", stack()[0][3]) + return 0 + except CalledProcessError, msg: + if logLevel.debug == True: + logger.operationsLog(str(msg), "Error", stack()[0][3]) + logger.writeToFile(str(msg), "Error", stack()[0][3]) + return 0 + + """ + + + osName = Name of OS, with which this image should be created. + imgDestination = Destination on disk where this image should be placed. + imgName = Name of vps, this will be combined with imgDestination. + size = Size in GBs. + format = Examples, qcow2, img, qcow, recommend is qcow2. + uploadSource = An array containing complete path of files to be uploaded to the image after creation. + UploadDestination = Corressponding array of upload source, defining upload destination of files. + + -- + + vmName = Name of the virtual machine, usually the IP Address. + vmRam = Ram to be assigned to this virtual machine. + vmVCPUs = Virtual CPUs to be assigned to this virtual machine. + diskImage = A complete path to disk image for this virtual machine. + vncPort = VNC Port for this virtual machine. + osType = OS Type e.g. linux,windows. + osVariant = OS Variant e.g. centos 6, centos 7. + bridgeName = Bridge name to which the interface of this VM will be attached. + + """ + + @staticmethod + def createVirtualMachine(vmName, package, rootPassword, vmVCPUs, vmRam, vncHost, vncPort, bridgeName, ipAddress, netmask, gateway, hostName, webSocketPort, vncPassword): + try: + + logger.operationsLog('Starting to create virtual machine: ' + vmName, 'Info', stack()[0][3]) + + ## + + uploadSource = virtualMachineAPI.setupNetworkingFiles(vmName, ipAddress, netmask, gateway, hostName) + + ## + if virtualMachineAPI.setupVMDisk(vmName, package, uploadSource, rootPassword) == 0: + return 0 + + ## + + if virtualMachineAPI.bootVirtualMachine(vmName, vmVCPUs, vmRam, vncHost, vncPort, bridgeName, webSocketPort, vncPassword) == 0: + return 0 + + ## + + logger.operationsLog('Virtual machine ' + vmName + ' successfully created.', 'Success', stack()[0][3]) + + return 1 + + except BaseException, msg: + if logLevel.debug == True: + logger.operationsLog(str(msg), "Error", stack()[0][3]) + logger.writeToFile(str(msg), "Error", stack()[0][3]) + return 0 + + +#virtualMachineAPI.createVirtualMachine('192.111.145.237', 'forthPlan', 'litespeed12', '2', '2048', '192.111.145.234', '5904','virbr0','192.111.145.237','255.255.255.248','192.111.145.233','usman.cybertronproject.com') + +#print virtualMachineAPI.deleteVirtualMachine('109.238.12.214') +#print virtualMachineAPI.revertToSnapshot('109.238.12.214','CyberPanel') +#virtualMachineAPI.softReboot('109.238.12.214') + + @staticmethod + def isActive(virtualMachineName): + try: + obtainStatus, virtualMachine = virtualMachineAPI.obtainVirtualMachineObject(virtualMachineName) + if obtainStatus == 1: + if virtualMachine.isActive(): + return 1 + else: + return 0 + else: + return 0 + + except BaseException, msg: + if logLevel.debug == True: + logger.operationsLog(str(msg), "Error", stack()[0][3]) + logger.writeToFile(str(msg), "Error", stack()[0][3]) + return 0 + + @staticmethod + def getCurrentUsedRam(virtualMachineName): + try: + obtainStatus, virtualMachine = virtualMachineAPI.obtainVirtualMachineObject(virtualMachineName) + if obtainStatus == 1: + if virtualMachine.isActive(): + memStats = virtualMachine.memoryStats() + return int(memStats['unused']/1024) + else: + return 0 + else: + return 0 + + except BaseException, msg: + if logLevel.debug == True: + logger.operationsLog(str(msg), "Error", stack()[0][3]) + logger.writeToFile(str(msg), "Error", stack()[0][3]) + return 0 + + @staticmethod + def getBandwidthUsage(virtualMachineName): + try: + obtainStatus, virtualMachine = virtualMachineAPI.obtainVirtualMachineObject(virtualMachineName) + if obtainStatus == 1: + if virtualMachine.isActive(): + tree = ElementTree.fromstring(virtualMachine.XMLDesc()) + iface = tree.find('devices/interface/target').get('dev') + memStats = virtualMachine.interfaceStats(iface) + ## memStats[0] are read bytes, memStats[4] write bytes + return (memStats[0] + memStats[4])/(1024 * 1024) + else: + return 0 + else: + return 0 + + except BaseException, msg: + if logLevel.debug == True: + logger.operationsLog(str(msg), "Error", stack()[0][3]) + logger.writeToFile(str(msg), "Error", stack()[0][3]) + return 0 + + @staticmethod + def calculateDiskPercentage(virtualMachineName, actualDisk): + try: + vpsImagePath = '/var/lib/libvirt/images/' + virtualMachineName + ".qcow2" + sizeInMB = float(path.getsize(vpsImagePath)) / (1024.0 * 1024) + diskUsagePercentage = float(100) / float((int(actualDisk.rstrip('GB')) * 1024)) + diskUsagePercentage = float(diskUsagePercentage) * float(sizeInMB) + diskUsagePercentage = int(diskUsagePercentage) + + if diskUsagePercentage > 100: + return 100, sizeInMB + + return diskUsagePercentage, sizeInMB + except BaseException, msg: + if logLevel.debug == True: + logger.operationsLog(str(msg), "Error", stack()[0][3]) + logger.writeToFile(str(msg), "Error", stack()[0][3]) + return 0,0 + + @staticmethod + def calculateRamPercentage(virtualMachineName, actualRam): + try: + unUsedRam = virtualMachineAPI.getCurrentUsedRam(virtualMachineName) + usedRam = int(actualRam.rstrip('MB')) - unUsedRam + + ramUsagePercentage = float(100) / int(actualRam.rstrip('MB')) + ramUsagePercentage = int(float(ramUsagePercentage) * float(usedRam)) + + if ramUsagePercentage > 100: + return 100 + + return ramUsagePercentage + + except BaseException, msg: + if logLevel.debug == True: + logger.operationsLog(str(msg), "Error", stack()[0][3]) + logger.writeToFile(str(msg), "Error", stack()[0][3]) + return 0 + + @staticmethod + def calculateBWPercentage(virtualMachineName, actualBW): + try: + usedBW = virtualMachineAPI.getBandwidthUsage(virtualMachineName) + availBW = int(actualBW.rstrip('TB')) * 1024 * 1024 + + bwPercentage = float(100) / availBW + bwPercentage = int(float(bwPercentage) * usedBW) + + if bwPercentage > 100: + return 100 + + return bwPercentage + + except BaseException, msg: + if logLevel.debug == True: + logger.operationsLog(str(msg), "Error", stack()[0][3]) + logger.writeToFile(str(msg), "Error", stack()[0][3]) + return 0 + + @staticmethod + def changeHostname(virtualMachineName, newHostname): + try: + command = "virt-customize -d " + virtualMachineName + " --hostname " + newHostname + call(split(command)) + + except BaseException, msg: + if logLevel.debug == True: + logger.operationsLog(str(msg), "Error", stack()[0][3]) + logger.writeToFile(str(msg), "Error", stack()[0][3]) + return 0, str(msg) + + @staticmethod + def changeRootPassword(virtualMachineName, newPassword): + try: + command = "virt-customize -d " + virtualMachineName + " --root-password password:" + newPassword + call(split(command)) + except BaseException, msg: + if logLevel.debug == True: + logger.operationsLog(str(msg), "Error", stack()[0][3]) + logger.writeToFile(str(msg), "Error", stack()[0][3]) + return 0, str(msg) + + @staticmethod + def createSnapshot(virtualMachineName, snapshotName): + try: + command = "virsh snapshot-create-as --domain " + virtualMachineName + " --name " + snapshotName + call(split(command)) + except BaseException, msg: + if logLevel.debug == True: + logger.operationsLog(str(msg), "Error", stack()[0][3]) + logger.writeToFile(str(msg), "Error", stack()[0][3]) + return 0, str(msg) + + @staticmethod + def deleteSnapshot(virtualMachineName, snapshotName): + try: + command = "virsh snapshot-delete --domain " + virtualMachineName + " --snapshotname " + snapshotName + call(split(command)) + except BaseException, msg: + if logLevel.debug == True: + logger.operationsLog(str(msg), "Error", stack()[0][3]) + logger.writeToFile(str(msg), "Error", stack()[0][3]) + return 0, str(msg) \ No newline at end of file diff --git a/CyberTronAPI/virtualMachineAPIOpenVZ.py b/CyberTronAPI/virtualMachineAPIOpenVZ.py new file mode 100755 index 000000000..3e52e73fb --- /dev/null +++ b/CyberTronAPI/virtualMachineAPIOpenVZ.py @@ -0,0 +1,668 @@ +from CyberTronLogger import CyberTronLogger as logger +from inspect import stack +from shlex import split +from subprocess import call, CalledProcessError +from os.path import join +from os import remove,path +from random import randint +from shutil import move +from time import sleep +from logLevel import logLevel +from multiprocessing import Process + +class virtualMachineAPIOpenVZ: + ## os.path.join + templatesPath = join('/var', 'lib', 'libvirt', 'templates') + imagesPath = join('/vz', 'root') + defaultInterface = 'eth0' + backupPath = join('/vz','dump') + + @staticmethod + def setupNetworkingFiles(vmName, osName, ipAddress, netmask, gateway, hostName): + try: + + if logLevel.debug == True: + logger.operationsLog('Setting up network for: ' + vmName + '.', 'Debug', stack()[0][3]) + + uploadSource = [] + + if osName.find("centos") > -1: + ###### /etc/sysconfig/network-scripts/ifcfg-eth0 + + eth0 = "ifcfg-eth0_" + str(randint(10000, 99999)) + eth0File = open(eth0, 'w') + + eth0File.writelines('DEVICE="eth0"\n') + eth0File.writelines('NM_CONTROLLED="yes"\n') + eth0File.writelines('ONBOOT=yes\n') + eth0File.writelines('TYPE=Ethernet\n') + eth0File.writelines('BOOTPROTO=static\n') + eth0File.writelines('NAME="System eth0"\n') + eth0File.writelines('IPADDR=' + ipAddress + '\n') + eth0File.writelines('NETMASK=' + netmask + '\n') + + eth0File.close() + + uploadSource.append(eth0) + + ###### /etc/sysconfig/network + + network = "network_" + str(randint(10000, 99999) + 1) + networkFile = open(network, 'w') + + networkFile.writelines('NETWORKING=yes\n') + networkFile.writelines('HOSTNAME=' + hostName + '\n') + networkFile.writelines('GATEWAY=' + gateway + '\n') + + networkFile.close() + + uploadSource.append(network) + + ###### /etc/resolv.conf + + resolv = "resolv_" + str(randint(10000, 99999) + 2) + resolvFile = open(resolv, 'w') + + resolvFile.writelines("nameserver 8.8.8.8\n") + + resolvFile.close() + + uploadSource.append(resolv) + elif osName.find("debian") > -1 or osName.find("ubuntu") > -1: + + ###### /etc/network/interfaces + + eth0 = "interfaces_" + str(randint(10000, 99999)) + eth0File = open(eth0, 'w') + + eth0File.writelines('# This file describes the network interfaces available on your system\n') + eth0File.writelines('# and how to activate them. For more information, see interfaces(5).\n') + + eth0File.writelines('\n') + + eth0File.writelines('# The loopback network interface\n') + eth0File.writelines('auto lo\n') + eth0File.writelines('iface lo inet loopback\n') + + eth0File.writelines('\n') + + ## To deal with Debian 9.3 and ubuntu 16.04 issue. + + eth0File.writelines('# The primary network interface\n') + + + eth0File.writelines('allow-hotplug eth0\n') + eth0File.writelines('iface eth0 inet static\n') + + eth0File.writelines(' address ' + ipAddress + '\n') + eth0File.writelines(' netmask ' + netmask + '\n') + eth0File.writelines(' gateway ' + gateway + '\n') + eth0File.writelines('# dns-* options are implemented by the resolvconf package, if installed\n') + eth0File.writelines('dns-nameservers 8.8.8.8\n') + eth0File.writelines('dns-search com\n') + + eth0File.close() + + uploadSource.append(eth0) + elif osName.find("fedora") > -1: + + ###### /etc/sysconfig/network-scripts/ifcfg-ens3 + + eth0 = "interfaces_" + str(randint(10000, 99999)) + eth0File = open(eth0, 'w') + + eth0File.writelines('TYPE=Ethernet\n') + eth0File.writelines('PROXY_METHOD=none\n') + + eth0File.writelines('BROWSER_ONLY=no\n') + eth0File.writelines('BOOTPROTO=none\n') + eth0File.writelines('DEFROUTE=yes\n') + + eth0File.writelines('IPV4_FAILURE_FATAL=no\n') + eth0File.writelines('IPV6INIT=yes\n') + eth0File.writelines('IPV6_AUTOCONF=yes\n') + + eth0File.writelines('IPV6_DEFROUTE=yes\n') + eth0File.writelines('IPV6_FAILURE_FATAL=no\n') + eth0File.writelines('IPV6_ADDR_GEN_MODE=stable-privacy\n') + eth0File.writelines('NAME=eth0\n') + eth0File.writelines('ONBOOT=yes\n') + eth0File.writelines('AUTOCONNECT_PRIORITY=-999\n') + + eth0File.writelines('DEVICE=eth0\n') + eth0File.writelines('IPADDR=' + ipAddress + '\n') + eth0File.writelines('NETMASK=' + netmask + '\n') + eth0File.writelines('GATEWAY=' + gateway + '\n') + eth0File.writelines('DNS1=8.8.8.8\n') + eth0File.writelines('IPV6_PRIVACY=no\n') + + eth0File.close() + uploadSource.append(eth0) + + if logLevel.debug == True: + logger.operationsLog('Network settings installed for: ' + vmName + '.', 'Debug', stack()[0][3]) + + return uploadSource + + + except BaseException, msg: + if logLevel.debug == True: + logger.operationsLog(str(msg), "Error", stack()[0][3]) + logger.writeToFile(str(msg), "Error", stack()[0][3]) + return 0 + + @staticmethod + def createContainer(vmName, containerID, osTemplate): + try: + + command = "vzctl create " + containerID + " --ostemplate " + osTemplate + result = call(split(command)) + + if result == 1: + raise CalledProcessError + + if logLevel.debug == True: + logger.operationsLog("Container successfully created for: " + vmName + ".", "Debug", + stack()[0][3]) + return 1 + + except BaseException, msg: + if logLevel.debug == True: + logger.operationsLog(str(msg), "Error", stack()[0][3]) + logger.writeToFile(str(msg), "Error", stack()[0][3]) + return 0 + except CalledProcessError, msg: + if logLevel.debug == True: + logger.operationsLog(str(msg), "Error", stack()[0][3]) + logger.writeToFile(str(msg), "Error", stack()[0][3]) + return 0 + + @staticmethod + def bootVirtualMachine(vmName, osTemplate, containerID, rootPassword, hostName, macAddress, uploadSource, cpuUnits, + cpuPercentage, vmVCPUs, vmRam, vmSwap, burstVMRam, size, + dnsNSOne="8.8.8.8", dnsNSTwo="8.8.4.4", + ioPriority=3, uploadSpeed=0, bandwidthSuspend=1, debug=False): + try: + ioPriority = str(ioPriority) + + command = "vzctl set " + containerID + " --save --name " + vmName + " --onboot yes --hostname " + hostName + \ + " --netif_add eth0,,," + macAddress + " --nameserver " + dnsNSOne + " --nameserver " + dnsNSTwo + \ + " --cpus " + vmVCPUs + " --ram " + vmRam + " --swap " + vmSwap + " --diskspace " + size + \ + " --userpasswd root:" + rootPassword + " --ioprio " + ioPriority + " --cpuunits " + cpuUnits + \ + " --cpulimit " + cpuPercentage + + + result = call(split(command)) + + if result == 1: + raise CalledProcessError + else: + pass + + + + command = "vzctl start " + containerID + + + result = call(split(command)) + + if result == 1: + raise CalledProcessError + else: + pass + + sleep(2) + + finalVMPath = join(virtualMachineAPIOpenVZ.imagesPath,containerID) + + if osTemplate.find('centos') > -1: + move(uploadSource[0],finalVMPath + '/etc/sysconfig/network-scripts/ifcfg-eth0') + move(uploadSource[1], finalVMPath + '/etc/sysconfig/network') + move(uploadSource[2], finalVMPath + '/etc/resolv.conf') + elif osTemplate.find('debian') > -1: + move(uploadSource[0], finalVMPath + '/etc/network/interfaces') + elif osTemplate.find('ubuntu') > -1: + move(uploadSource[0], finalVMPath + '/etc/network/interfaces') + elif osTemplate.find('fedora') > -1: + move(uploadSource[0], finalVMPath + '/etc/sysconfig/network-scripts/ifcfg-eth0') + + command = "vzctl exec " + containerID + " /etc/init.d/network restart" + + + result = call(split(command)) + + if result == 1: + raise CalledProcessError + else: + pass + + return 1 + + + except BaseException, msg: + if logLevel.debug == True: + logger.operationsLog(str(msg), "Error", stack()[0][3]) + logger.writeToFile(str(msg), "Error", stack()[0][3]) + return 0 + except CalledProcessError, msg: + if logLevel.debug == True: + logger.operationsLog(str(msg), "Error", stack()[0][3]) + logger.writeToFile(str(msg), "Error", stack()[0][3]) + return 0 + + + + """ + + vmName = Name of the virtual machine, usually the IP Address. + containerID = Container ID of VPS, which usually identify OpenVZ VPS. Starts 100 and above. + osTemplate = osTemplate that will be used to boot OpenVZ Container. + rootPassword = VPS Root Password. + size = Size in GBs of OpenVZ Container. + vmRam = Guranteed dedicated virtual machine ram. + burstVMRam = Burstable ram, ram that VM can acquire if it is avaiable by host node. + bandwidth = Bandwidth allowed to container. + """ + + @staticmethod + def createVirtualMachine(vmName, containerID, osTemplate, rootPassword, size, vmRam, vmSwap, burstVMRam, bandwidth, cpuUnits, + vmVCPUs,cpuPercentage, ipAddress, netmask, gateway, hostName, macAddress, + dnsNSOne = "8.8.8.8", dnsNSTwo = "8.8.4.4", networkSpeed = '0', + ioPriority = 3, uploadSpeed = 0, bandwidthSuspend = 1): + try: + + logger.operationsLog('Starting to create virtual machine: ' + vmName, 'Info', stack()[0][3]) + + ## + + uploadSource = virtualMachineAPIOpenVZ.setupNetworkingFiles(vmName, osTemplate, ipAddress, netmask, gateway, hostName) + + ## + + if virtualMachineAPIOpenVZ.createContainer(vmName, containerID, osTemplate) == 0: + raise BaseException("Failed to create container.") + + ## + + if virtualMachineAPIOpenVZ.bootVirtualMachine(vmName, osTemplate, containerID, rootPassword, hostName, macAddress, uploadSource, + cpuUnits, cpuPercentage, vmVCPUs, vmRam, vmSwap, burstVMRam, + size, dnsNSOne, dnsNSTwo, + ioPriority, uploadSpeed,bandwidthSuspend) == 0: + raise BaseException("Failed to boot container.") + + + #if virtualMachineAPIOpenVZ.limitContainerSpeed(containerID, ipAddress, virtualMachineAPIOpenVZ.defaultInterface, networkSpeed) == 0: + # raise BaseException("Failed to set network limits.") + + ## + + logger.operationsLog('Virtual machine ' + vmName + ' successfully created.', 'Success', stack()[0][3]) + + return 1 + + except BaseException, msg: + if logLevel.debug == True: + logger.operationsLog(str(msg), "Error", stack()[0][3]) + logger.writeToFile(str(msg), "Error", stack()[0][3]) + return 0 + + @staticmethod + def deleteVirtualMachine(containerID): + try: + + result = virtualMachineAPIOpenVZ.hardShutdown(containerID) + + if result[0] == 1: + + command = "vzctl destroy " + containerID + result = call(split(command)) + + if result == 1: + raise CalledProcessError + else: + pass + + return 1,'No error.' + + else: + return 0, 'Failed to stop virtual machine.' + + + except BaseException, msg: + if logLevel.debug == True: + logger.operationsLog(str(msg), "Error", stack()[0][3]) + logger.writeToFile(str(msg), "Error", stack()[0][3]) + return 0, str(msg) + except CalledProcessError, msg: + if logLevel.debug == True: + logger.operationsLog(str(msg), "Error", stack()[0][3]) + logger.writeToFile(str(msg), "Error", stack()[0][3]) + return 0, str(msg) + + @staticmethod + def softReboot(containerID): + try: + + command = "vzctl restart " + containerID + + result = call(split(command)) + + if result == 1: + raise CalledProcessError + else: + pass + + return 1,'No error.' + + except BaseException, msg: + if logLevel.debug == True: + logger.operationsLog(str(msg), "Error", stack()[0][3]) + logger.writeToFile(str(msg), "Error", stack()[0][3]) + return 0, str(msg) + except CalledProcessError, msg: + if logLevel.debug == True: + logger.operationsLog(str(msg), "Error", stack()[0][3]) + logger.writeToFile(str(msg), "Error", stack()[0][3]) + return 0, str(msg) + + @staticmethod + def hardShutdown(containerID): + try: + + command = "vzctl stop " + containerID + + result = call(split(command)) + + if result == 1: + raise CalledProcessError + else: + pass + + return 1,'No error.' + + except BaseException, msg: + if logLevel.debug == True: + logger.operationsLog(str(msg), "Error", stack()[0][3]) + logger.writeToFile(str(msg), "Error", stack()[0][3]) + return 0, str(msg) + except CalledProcessError, msg: + if logLevel.debug == True: + logger.operationsLog(str(msg), "Error", stack()[0][3]) + logger.writeToFile(str(msg), "Error", stack()[0][3]) + return 0, str(msg) + + @staticmethod + def startContainer(containerID): + try: + + command = "vzctl start " + containerID + + result = call(split(command)) + + if result == 1: + raise CalledProcessError + else: + pass + + return 1,'No error.' + + except BaseException, msg: + if logLevel.debug == True: + logger.operationsLog(str(msg), "Error", stack()[0][3]) + logger.writeToFile(str(msg), "Error", stack()[0][3]) + return 0, str(msg) + except CalledProcessError, msg: + if logLevel.debug == True: + logger.operationsLog(str(msg), "Error", stack()[0][3]) + logger.writeToFile(str(msg), "Error", stack()[0][3]) + return 0, str(msg) + + @staticmethod + def suspendContainer(containerID): + try: + + command = "vzctl suspend " + containerID + + result = call(split(command)) + + if result == 1: + raise CalledProcessError + else: + pass + + return 1,'No error.' + + except BaseException, msg: + if logLevel.debug == True: + logger.operationsLog(str(msg), "Error", stack()[0][3]) + logger.writeToFile(str(msg), "Error", stack()[0][3]) + return 0, str(msg) + except CalledProcessError, msg: + if logLevel.debug == True: + logger.operationsLog(str(msg), "Error", stack()[0][3]) + logger.writeToFile(str(msg), "Error", stack()[0][3]) + return 0, str(msg) + + @staticmethod + def resumeContainer(containerID): + try: + command = "vzctl resume " + containerID + + result = call(split(command)) + + if result == 1: + raise CalledProcessError + else: + pass + + return 1, 'No error.' + + except BaseException, msg: + if logLevel.debug == True: + logger.operationsLog(str(msg), "Error", stack()[0][3]) + logger.writeToFile(str(msg), "Error", stack()[0][3]) + return 0, str(msg) + except CalledProcessError, msg: + if logLevel.debug == True: + logger.operationsLog(str(msg), "Error", stack()[0][3]) + logger.writeToFile(str(msg), "Error", stack()[0][3]) + return 0, str(msg) + + @staticmethod + def limitContainerSpeed(containerID, containerIP, interface, interfaceLimit): + try: + ## Creating class + + command = 'tc class add dev ' + interface + ' parent 2:1 classid ' + '2:' + containerID + ' htb rate '+ interfaceLimit + + result = call(split(command)) + + if result == 1: + raise CalledProcessError + else: + pass + + ## Create IP Filter. + + command = 'tc filter add dev ' + interface + ' parent 2:0 protocol ip prio 1 u32 match ip src ' + containerIP + ' flowid 2:' + containerID + + result = call(split(command)) + + if result == 1: + raise CalledProcessError + else: + pass + + return 1 + + except BaseException, msg: + if logLevel.debug == True: + logger.operationsLog(str(msg), "Error", stack()[0][3]) + logger.writeToFile(str(msg), "Error", stack()[0][3]) + return 0 + except CalledProcessError, msg: + if logLevel.debug == True: + logger.operationsLog(str(msg), "Error", stack()[0][3]) + logger.writeToFile(str(msg), "Error", stack()[0][3]) + return 0 + + @staticmethod + def removeContainerSpeedLimit(containerID, interface): + try: + ## Removing filter. + + command = 'tc filter del dev ' + interface + ' parent 2:0 protocol ip prio 1 u32 flowid 2:' + containerID + + result = call(split(command)) + + if result == 1: + raise CalledProcessError + else: + pass + + ## Removing class. + + command = 'tc class del dev ' + interface + ' classid 2:' + containerID + + result = call(split(command)) + + if result == 1: + raise CalledProcessError + else: + pass + + return 1 + + except BaseException, msg: + if logLevel.debug == True: + logger.operationsLog(str(msg), "Error", stack()[0][3]) + logger.writeToFile(str(msg), "Error", stack()[0][3]) + return 0 + except CalledProcessError, msg: + if logLevel.debug == True: + logger.operationsLog(str(msg), "Error", stack()[0][3]) + logger.writeToFile(str(msg), "Error", stack()[0][3]) + return 0 + + + @staticmethod + def createBackup(containerID, suspend = False , stop = False): + try: + + statusFilePath = join(virtualMachineAPIOpenVZ.backupPath, 'vzdump-' + containerID + '.log') + + if path.exists(statusFilePath): + remove(statusFilePath) + + if suspend == True: + command = 'vzdump --compress --suspend ' + containerID + elif stop == True: + command = 'vzdump --compress --stop ' + containerID + else: + command = 'vzdump --compress ' + containerID + + result = call(split(command)) + + if result == 1: + raise CalledProcessError + else: + pass + + return 1 + + except BaseException, msg: + if logLevel.debug == True: + logger.operationsLog(str(msg), "Error", stack()[0][3]) + logger.writeToFile(str(msg), "Error", stack()[0][3]) + return 0 + except CalledProcessError, msg: + if logLevel.debug == True: + logger.operationsLog(str(msg), "Error", stack()[0][3]) + logger.writeToFile(str(msg), "Error", stack()[0][3]) + return 0 + + @staticmethod + def initiateBackup(containerID, suspend=False, stop=False): + try: + p = Process(target=virtualMachineAPIOpenVZ.createBackup, args=(containerID, suspend, stop,)) + p.start() + # pid = open(backupPath + 'pid', "w") + # pid.write(str(p.pid)) + # pid.close() + except BaseException, msg: + if logLevel.debug == True: + logger.operationsLog(str(msg), "Error", stack()[0][3]) + logger.writeToFile(str(msg), "Error", stack()[0][3]) + return 0 + except CalledProcessError, msg: + if logLevel.debug == True: + logger.operationsLog(str(msg), "Error", stack()[0][3]) + logger.writeToFile(str(msg), "Error", stack()[0][3]) + return 0 + + + @staticmethod + def checkBackupCreationStatus(containerID): + try: + + statusFilePath = join(virtualMachineAPIOpenVZ.backupPath,'vzdump-' + containerID + '.log') + + statusFile = open(statusFilePath, 'r') + dataInStatusFile = statusFile.read() + statusFile.close() + + if dataInStatusFile.find('Finished Backup of') > -1: + return 1,dataInStatusFile + else: + return 0,dataInStatusFile + + + except BaseException, msg: + if logLevel.debug == True: + logger.operationsLog(str(msg), "Error", stack()[0][3]) + logger.writeToFile(str(msg), "Error", stack()[0][3]) + return 0 + except CalledProcessError, msg: + if logLevel.debug == True: + logger.operationsLog(str(msg), "Error", stack()[0][3]) + logger.writeToFile(str(msg), "Error", stack()[0][3]) + return 0 + + +def main(): + + virtualMachineAPIOpenVZ.initiateBackup('105') + + while(1): + retValue = virtualMachineAPIOpenVZ.checkBackupCreationStatus('105') + + if retValue[0] == 0: + print retValue[1] + else: + print "Completed" + break + +#main() + + + + + + +virtualMachineAPIOpenVZ.createVirtualMachine('192.111.145.235','102',"centos-7-x86_64-minimal","litespeed12", + '70G','4G','2G','6G','100GB','900','2','20%','192.111.145.235','255.255.255.248', + '192.111.145.233','cybertronproject.com','FE:FF:FF:FF:FF:FF', '8.8.8.8', '8.8.4.4', + '2Mbit', 4, 0, 1) + + +#virtualMachineAPIOpenVZ.removeContainerSpeedLimit('105','eth0') +#virtualMachineAPIOpenVZ.limitContainerSpeed('105','192.111.145.238','eth0','256Kbit') + +#print virtualMachineAPI.deleteVirtualMachine('109.238.12.214') + +#print virtualMachineAPI.revertToSnapshot('109.238.12.214','CyberPanel') + +#virtualMachineAPIOpenVZ.deleteVirtualMachine('102') +#virtualMachineAPIOpenVZ.softReboot('102') +#virtualMachineAPIOpenVZ.hardShutdown('102') +#virtualMachineAPIOpenVZ.startContainer('102') diff --git a/backup/static/backup/backup.js b/backup/static/backup/backup.js index b83f9bcce..159550915 100644 --- a/backup/static/backup/backup.js +++ b/backup/static/backup/backup.js @@ -1550,4 +1550,480 @@ app.controller('remoteBackupControl', function($scope, $http, $timeout) { }); -///** Backup site ends **/// \ No newline at end of file +///** Backup site ends **/// + + +/////////////// Snapshots + +/* Java script code for Snapshots */ +app.controller('snapshotsCTRL', function($scope,$http) { + + $scope.getCurrentSnapshots = function(){ + + $scope.tronLoading = false; + + var url = "/backup/fetchCurrentSnapshots"; + + var data = { + hostName: $("#hostname").text() + }; + + var config = { + headers : { + 'X-CSRFToken': getCookie('csrftoken') + } + }; + + $http.post(url, data,config).then(ListInitialDatas, cantLoadInitialDatas); + + + function ListInitialDatas(response) { + + $scope.tronLoading = true; + $scope.snapshotTable = false; + + if(response.data.success === 1){ + + $scope.snapshots = JSON.parse(response.data.data); + } + else + { + new PNotify({ + title: 'Operation Failed!', + 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.getCurrentSnapshots(); + + /// Administrative Tasks + + $scope.tronLoading = true; + $scope.createSnapshotBox = true; + + + $scope.showSnapshotForm = function () { + $scope.createSnapshotBox = false; + $scope.createSnapshotBTN = true; + $scope.snapshotTable = true; + + }; + + + $scope.createSnapShot = function(){ + + $scope.tronLoading = false; + + + var url = "/backup/submitSnapshotCreation"; + + var data = { + hostName: $("#hostname").text(), + snapshotName: $scope.snapshotName + }; + + var config = { + headers : { + 'X-CSRFToken': getCookie('csrftoken') + } + }; + + $http.post(url, data,config).then(ListInitialDatas, cantLoadInitialDatas); + + + function ListInitialDatas(response) { + + $scope.tronLoading = true; + + if(response.data.success === 1){ + + new PNotify({ + title: 'Operation Successfull!', + text: response.data.successMessage, + type:'success' + }); + + $scope.getCurrentSnapshots(); + $scope.createSnapshotBox = true; + $scope.createSnapshotBTN = false; + + } + else + { + + new PNotify({ + title: 'Operation failed!', + text: response.data.error_message, + type:'error' + }); + } + } + function cantLoadInitialDatas(response) { + + $scope.tronLoading = true; + new PNotify({ + title: 'Operation failed!', + text: "Could not connect to server. Please refresh this page.", + type:'error' + }); + + + } + + }; + $scope.deleteSnapshot = function(snapshotName){ + + $scope.tronLoading = false; + + + var url = "/backup/deletSnapshot"; + + var data = { + hostName: $("#hostname").text(), + snapshotName: snapshotName + }; + + var config = { + headers : { + 'X-CSRFToken': getCookie('csrftoken') + } + }; + + $http.post(url, data,config).then(ListInitialDatas, cantLoadInitialDatas); + + + function ListInitialDatas(response) { + + $scope.tronLoading = true; + + if(response.data.success === 1){ + + new PNotify({ + title: 'Operation Successfull!', + text: response.data.successMessage, + type:'success' + }); + + $scope.getCurrentSnapshots(); + + } + else + { + + new PNotify({ + title: 'Operation failed!', + text: response.data.error_message, + type:'error' + }); + } + } + function cantLoadInitialDatas(response) { + + $scope.tronLoading = true; + new PNotify({ + title: 'Operation failed!', + text: "Could not connect to server. Please refresh this page.", + type:'error' + }); + + + } + + }; + $scope.revertToSnapshot = function(snapshotName){ + + $scope.tronLoading = false; + + + var url = "/backup/revertToSnapshot"; + + var data = { + hostName: $("#hostname").text(), + snapshotName: snapshotName + }; + + var config = { + headers : { + 'X-CSRFToken': getCookie('csrftoken') + } + }; + + $http.post(url, data,config).then(ListInitialDatas, cantLoadInitialDatas); + + + function ListInitialDatas(response) { + + $scope.tronLoading = true; + + if(response.data.success === 1){ + + new PNotify({ + title: 'Operation Successfull!', + text: response.data.successMessage, + type:'success' + }); + + } + else + { + + new PNotify({ + title: 'Operation failed!', + text: response.data.error_message, + type:'error' + }); + } + } + function cantLoadInitialDatas(response) { + + $scope.tronLoading = true; + new PNotify({ + title: 'Operation failed!', + text: "Could not connect to server. Please refresh this page.", + type:'error' + }); + + + } + + }; + + + $scope.changeRootPassword = function(vpsID){ + + $scope.tronLoading = false; + + + var url = "/vps/changeRootPassword"; + + var data = { + hostName: $("#vpsHostname").text(), + newPassword: $scope.newPassword + }; + + var config = { + headers : { + 'X-CSRFToken': getCookie('csrftoken') + } + }; + + $http.post(url, data,config).then(ListInitialDatas, cantLoadInitialDatas); + + + function ListInitialDatas(response) { + + $scope.tronLoading = true; + + if(response.data.success === 1){ + + $scope.successMessage = response.data.successMessage; + + new PNotify({ + title: 'Operation Successfull!', + text: response.data.successMessage, + type:'success' + }); + + } + else + { + new PNotify({ + title: 'Operation failed!', + text: response.data.error_message, + type:'error' + }); + } + } + function cantLoadInitialDatas(response) { + + $scope.tronLoading = true; + new PNotify({ + title: 'Operation failed!', + text: "Could not connect to server. Please refresh this page.", + type:'error' + }); + + + } + + }; + $scope.reinstallOS = function(vpsID){ + + $scope.tronLoading = false; + + + var url = "/vps/reInstallOS"; + + var data = { + hostName: $("#vpsHostname").text(), + rootPassword: $scope.reinstallPassword + }; + + var config = { + headers : { + 'X-CSRFToken': getCookie('csrftoken') + } + }; + + $http.post(url, data,config).then(ListInitialDatas, cantLoadInitialDatas); + + + function ListInitialDatas(response) { + + $scope.tronLoading = true; + + if(response.data.success === 1){ + + $scope.successMessage = response.data.successMessage; + + new PNotify({ + title: 'Operation Successfull!', + text: response.data.successMessage, + type:'success' + }); + + } + else + { + + new PNotify({ + title: 'Operation failed!', + text: response.data.error_message, + type:'error' + }); + } + } + function cantLoadInitialDatas(response) { + + $scope.tronLoading = true; + new PNotify({ + title: 'Operation failed!', + text: "Could not connect to server. Please refresh this page.", + type:'error' + }); + + + } + + }; + + + $scope.restartVPS = function(vpsID){ + + $scope.tronLoading = false; + $scope.poolCreationFailed = true; + $scope.poolCreated = true; + $scope.couldNotConnect = true; + + + + var url = "/vps/restartVPS"; + + var data = {vpsID: vpsID}; + + var config = { + headers : { + 'X-CSRFToken': getCookie('csrftoken') + } + }; + + $http.post(url, data,config).then(ListInitialDatas, cantLoadInitialDatas); + + + function ListInitialDatas(response) { + + if(response.data.success === 1){ + + $scope.tronLoading = true; + $scope.poolCreationFailed = true; + $scope.poolCreated = false; + $scope.couldNotConnect = true; + $scope.successMessage = response.data.successMessage; + $scope.getFurtherVPS(currentPageNumber); + } + else + { + $scope.tronLoading = true; + $scope.poolCreationFailed = false; + $scope.poolCreated = true; + $scope.couldNotConnect = true; + $scope.errorMessage = response.data.error_message; + + } + } + function cantLoadInitialDatas(response) { + $scope.tronLoading = true; + $scope.poolCreationFailed = true; + $scope.poolCreated = true; + $scope.couldNotConnect = false; + + } + + }; + $scope.shutdownVPS = function(vpsID){ + + $scope.tronLoading = false; + $scope.poolCreationFailed = true; + $scope.poolCreated = true; + $scope.couldNotConnect = true; + + + + var url = "/vps/shutdownVPS"; + + var data = {vpsID: vpsID}; + + var config = { + headers : { + 'X-CSRFToken': getCookie('csrftoken') + } + }; + + $http.post(url, data,config).then(ListInitialDatas, cantLoadInitialDatas); + + + function ListInitialDatas(response) { + + if(response.data.success === 1){ + + $scope.tronLoading = true; + $scope.poolCreationFailed = true; + $scope.poolCreated = false; + $scope.couldNotConnect = true; + $scope.successMessage = response.data.successMessage; + $scope.getFurtherVPS(currentPageNumber); + } + else + { + $scope.tronLoading = true; + $scope.poolCreationFailed = false; + $scope.poolCreated = true; + $scope.couldNotConnect = true; + $scope.errorMessage = response.data.error_message; + + } + } + function cantLoadInitialDatas(response) { + $scope.tronLoading = true; + $scope.poolCreationFailed = true; + $scope.poolCreated = true; + $scope.couldNotConnect = false; + + } + + }; + +}); +/* Java script code for Snapshots ends here */ \ No newline at end of file diff --git a/backup/templates/backup/createSnapshots.html b/backup/templates/backup/createSnapshots.html new file mode 100644 index 000000000..79e071e0d --- /dev/null +++ b/backup/templates/backup/createSnapshots.html @@ -0,0 +1,99 @@ +{% extends "baseTemplate/index.html" %} +{% load i18n %} +{% block title %}{% trans "Create Snapshots - CyberTron" %}{% endblock %} +{% block content %} + +{% load static %} +{% get_current_language as LANGUAGE_CODE %} + + +
+
+

{% trans "Snapshots" %}

+

{% trans "On this page you can create, delete or revert to Virtual Machine Snapshot." %}

+
+ +
+
+

+ {% trans "Snapshots for" %} {{ hostName }} +

+
+ + +
+ + +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + +
{% trans "ID" %}{% trans "VPS Name" %}{% trans "Snapshot Name" %}{% trans "Creation Time" %}{% trans "Operations" %}
+ + +
+ + + +
+ +
+ + + +
+ +
+ +
+
+ +
+ + +
+ +
+ +
+
+
+ + + + + + + +
+
+
+ + +
+ + +{% endblock %} \ No newline at end of file diff --git a/backup/urls.py b/backup/urls.py index df1efd2c8..e97f78abf 100644 --- a/backup/urls.py +++ b/backup/urls.py @@ -46,6 +46,14 @@ urlpatterns = [ url(r'^cancelRemoteBackup', views.cancelRemoteBackup, name='cancelRemoteBackup'), + ## Snapshots + + url(r'^revertToSnapshot$', views.revertToSnapshot, name='revertToSnapshot'), + url(r'^deletSnapshot$', views.deletSnapshot, name='deletSnapshot'), + url(r'^submitSnapshotCreation$', views.submitSnapshotCreation, name='submitSnapshotCreation'), + url(r'^fetchCurrentSnapshots$', views.fetchCurrentSnapshots, name='fetchCurrentSnapshots'), + url(r'^(?P(.*))/snapshots$', views.createSnapshots, name='createSnapshots'), + diff --git a/backup/views.py b/backup/views.py index 6bcac0d44..d92e5d1b2 100644 --- a/backup/views.py +++ b/backup/views.py @@ -1,12 +1,13 @@ # -*- coding: utf-8 -*- from __future__ import unicode_literals -from django.shortcuts import redirect -# Create your views here. +from django.shortcuts import redirect, HttpResponse, render import json from loginSystem.views import loadLoginPage from plogical.backupManager import BackupManager - +from loginSystem.models import Administrator +import plogical.CyberCPLogFileWriter as logging +from vpsManagement.vpsManager import VPSManager def loadBackupHome(request): try: @@ -213,3 +214,46 @@ def cancelRemoteBackup(request): return wm.cancelRemoteBackup(userID, json.loads(request.body)) except KeyError: return redirect(loadLoginPage) + + +## Snapshots + +def createSnapshots(request, hostName): + try: + userID = request.session['userID'] + vmm = VPSManager() + return vmm.createSnapshots(request, userID, hostName) + except KeyError: + return redirect(loadLoginPage) + +def fetchCurrentSnapshots(request): + try: + userID = request.session['userID'] + vmm = VPSManager() + return vmm.fetchCurrentSnapshots(userID, json.loads(request.body)) + except KeyError: + return redirect(loadLoginPage) + +def submitSnapshotCreation(request): + try: + userID = request.session['userID'] + vmm = VPSManager() + return vmm.submitSnapshotCreation(userID, json.loads(request.body)) + except KeyError: + return redirect(loadLoginPage) + +def deletSnapshot(request): + try: + userID = request.session['userID'] + vmm = VPSManager() + return vmm.deletSnapshot(userID, json.loads(request.body)) + except KeyError: + return redirect(loadLoginPage) + +def revertToSnapshot(request): + try: + userID = request.session['userID'] + vmm = VPSManager() + return vmm.revertToSnapshot(userID, json.loads(request.body)) + except KeyError: + return redirect(loadLoginPage) diff --git a/baseTemplate/templates/baseTemplate/homePageVMM.html b/baseTemplate/templates/baseTemplate/homePageVMM.html new file mode 100644 index 000000000..a280596cb --- /dev/null +++ b/baseTemplate/templates/baseTemplate/homePageVMM.html @@ -0,0 +1,85 @@ +{% extends "baseTemplate/indexVMM.html" %} +{% load i18n %} +{% block title %}{% trans "Home - CyberPanel" %}{% endblock %} +{% block content %} + + +{% get_current_language as LANGUAGE_CODE %} + + +
+
+

{% trans "Home" %}

+

{% trans "Use the tabs to navigate through the control panel." %}

+
+ + + +
+ + +{% endblock %} \ No newline at end of file diff --git a/baseTemplate/templates/baseTemplate/index.html b/baseTemplate/templates/baseTemplate/index.html index eb135bb4f..cdc804c98 100755 --- a/baseTemplate/templates/baseTemplate/index.html +++ b/baseTemplate/templates/baseTemplate/index.html @@ -68,10 +68,8 @@ - - -
+ - + \ No newline at end of file diff --git a/baseTemplate/templates/baseTemplate/indexVMM.html b/baseTemplate/templates/baseTemplate/indexVMM.html new file mode 100644 index 000000000..bcdfbedbc --- /dev/null +++ b/baseTemplate/templates/baseTemplate/indexVMM.html @@ -0,0 +1,392 @@ +{% load i18n %} +{% get_current_language as LANGUAGE_CODE %} + + + + + + + + + +{% block title %}Page Title{% endblock %} + + + + + {% load static %} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + +
+
+
+ + + + +
+ + + + +
+ +
+
+
+ + + + +
+
+
+
+
+
+
+ + + + + + + + + + + + + + + +
+ + \ No newline at end of file diff --git a/baseTemplate/urls.py b/baseTemplate/urls.py index b249bf99e..2d1253b23 100644 --- a/baseTemplate/urls.py +++ b/baseTemplate/urls.py @@ -11,9 +11,14 @@ urlpatterns = [ #url(r'^upgrade',views.upgrade, name='upgrade'), url(r'^UpgradeStatus',views.upgradeStatus, name='UpgradeStatus'), - url(r'^upgradeVersion',views.upgradeVersion, name='upgradeVersion'), + ## VMM + + url(r'^VMM$',views.VMM, name='VMM'), + + + ] \ No newline at end of file diff --git a/baseTemplate/views.py b/baseTemplate/views.py index 94731496c..229f4ea93 100644 --- a/baseTemplate/views.py +++ b/baseTemplate/views.py @@ -4,7 +4,6 @@ from __future__ import unicode_literals from django.shortcuts import render,redirect from django.http import HttpResponse from plogical.getSystemInformation import SystemInformation -from loginSystem.models import Administrator, ACL import json from loginSystem.views import loadLoginPage import re @@ -15,6 +14,7 @@ import shlex import os import plogical.CyberCPLogFileWriter as logging from plogical.acl import ACLManager +from plogical.aclVMM import vmmACLManager # Create your views here. @@ -36,6 +36,29 @@ def renderBase(request): except KeyError: return redirect(loadLoginPage) + +def VMM(request): + try: + userID = request.session['userID'] + currentACL = ACLManager.loadedACL(userID) + + if vmmACLManager.inspectHyperVisor() == 0: + return vmmACLManager.loadError() + + if currentACL['admin'] == 1: + admin = 1 + else: + admin = 0 + + cpuRamDisk = SystemInformation.cpuRamDisk() + + finaData = {"admin": admin,'ramUsage':cpuRamDisk['ramUsage'],'cpuUsage':cpuRamDisk['cpuUsage'],'diskUsage':cpuRamDisk['diskUsage'] } + + return render(request, 'baseTemplate/homePageVMM.html', finaData) + except KeyError: + return redirect(loadLoginPage) + + def getAdminStatus(request): try: val = request.session['userID'] diff --git a/hypervisor/__init__.py b/hypervisor/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/hypervisor/admin.py b/hypervisor/admin.py new file mode 100644 index 000000000..13be29d96 --- /dev/null +++ b/hypervisor/admin.py @@ -0,0 +1,6 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.contrib import admin + +# Register your models here. diff --git a/hypervisor/apps.py b/hypervisor/apps.py new file mode 100644 index 000000000..b3d993648 --- /dev/null +++ b/hypervisor/apps.py @@ -0,0 +1,8 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.apps import AppConfig + + +class HypervisorConfig(AppConfig): + name = 'hypervisor' diff --git a/hypervisor/hypervisor.py b/hypervisor/hypervisor.py new file mode 100644 index 000000000..0c3525fc0 --- /dev/null +++ b/hypervisor/hypervisor.py @@ -0,0 +1,144 @@ +#!/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 json +import subprocess +import shlex +from django.shortcuts import HttpResponse, render +from loginSystem.models import Administrator +from plogical.aclVMM import vmmACLManager +from plogical.acl import ACLManager +from models import HyberVisors + +class HVManager: + def loadHVHome(self, request = None, userID = None,): + try: + return render(request, 'hypervisor/indexVMM.html', {}) + except BaseException, msg: + return HttpResponse(str(msg)) + + def createHypervisor(self, request = None, userID = None,): + try: + currentACL = ACLManager.loadedACL(userID) + if vmmACLManager.currentContextPermission(currentACL, 'createHypervisor') == 0: + return ACLManager.loadError() + + ownerNames = ACLManager.loadAllUsers(userID) + + return render(request, 'hypervisor/createHyperVisor.html', {'ownerNames' : ownerNames}) + + except BaseException, msg: + return HttpResponse(str(msg)) + + def listHVs(self, request = None, userID = None,): + try: + currentACL = ACLManager.loadedACL(userID) + if vmmACLManager.currentContextPermission(currentACL, 'listHV') == 0: + return ACLManager.loadError() + + serverObjs = vmmACLManager.findServersObjs(currentACL, userID) + hvs = vmmACLManager.prepareServers(serverObjs) + ownerNames = ACLManager.loadAllUsers(userID) + + return render(request, 'hypervisor/listHV.html', {'hvs' : hvs, 'ownerNames' : ownerNames}) + + except BaseException, msg: + return HttpResponse(str(msg)) + + def submitCreateHyperVisor(self, userID = None, data = None): + try: + currentACL = ACLManager.loadedACL(userID) + if vmmACLManager.currentContextPermission(currentACL, 'createHypervisor') == 0: + return ACLManager.loadErrorJson() + + if HyberVisors.objects.all().count() == 1: + final_json = json.dumps({'status': 0, 'errorMessage': "Only one server is allowed at this time."}) + return HttpResponse(final_json) + + name = data['name'] + serverOwner = data['serverOwner'] + serverIP = data['serverIP'] + userName = data['userName'] + password = data['password'] + storagePath = data['storagePath'] + + hvOwner = Administrator.objects.get(userName=serverOwner) + + newHV = HyberVisors(hypervisorOwner=hvOwner, + hypervisorName=name, + hypervisorIP=serverIP, + hypervisorUserName=userName, + hypervisorPassword=password, + hypervisorStoragePath=storagePath) + newHV.save() + + + final_json = json.dumps({'status': 1, 'errorMessage': "None"}) + return HttpResponse(final_json) + + except BaseException, msg: + final_json = json.dumps({'status': 0, 'errorMessage': str(msg)}) + return HttpResponse(final_json) + + def submitHyperVisorChanges(self, userID = None, data = None): + try: + currentACL = ACLManager.loadedACL(userID) + if vmmACLManager.currentContextPermission(currentACL, 'listHV') == 0: + return ACLManager.loadErrorJson() + + name = data['name'] + serverOwner = data['serverOwner'] + userName = data['userName'] + password = data['password'] + storagePath = data['storagePath'] + + hvOwner = Administrator.objects.get(userName=serverOwner) + + modifyHV = HyberVisors.objects.get(hypervisorName=name) + modifyHV.hypervisorOwner = hvOwner + modifyHV.hypervisorUserName = userName + modifyHV.hypervisorPassword = password + modifyHV.hypervisorStoragePath = storagePath + + modifyHV.save() + + final_json = json.dumps({'status': 1, 'errorMessage': "None"}) + return HttpResponse(final_json) + + except BaseException, msg: + final_json = json.dumps({'status': 0, 'errorMessage': str(msg)}) + return HttpResponse(final_json) + + def controlCommands(self, userID = None, data = None): + try: + currentACL = ACLManager.loadedACL(userID) + if vmmACLManager.currentContextPermission(currentACL, 'listHV') == 0: + return ACLManager.loadErrorJson() + + hypervisorIP = data['hypervisorIP'] + action = data['action'] + + hv = HyberVisors.objects.get(hypervisorIP=hypervisorIP) + + if hypervisorIP == '127.0.0.1': + if action == 'restart': + command = 'sudo reboot' + ACLManager.executeCall(command) + elif action == 'shutdown': + command = 'sudo shutdown' + ACLManager.executeCall(command) + elif action == 'delete': + final_json = json.dumps({'status': 0, 'errorMessage': "Local Server can not be deleted."}) + return HttpResponse(final_json) + + final_json = json.dumps({'status': 1, 'errorMessage': "None"}) + return HttpResponse(final_json) + + except BaseException, msg: + final_json = json.dumps({'status': 0, 'errorMessage': str(msg)}) + return HttpResponse(final_json) \ No newline at end of file diff --git a/hypervisor/migrations/__init__.py b/hypervisor/migrations/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/hypervisor/models.py b/hypervisor/models.py new file mode 100644 index 000000000..02dbec752 --- /dev/null +++ b/hypervisor/models.py @@ -0,0 +1,13 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models +from loginSystem.models import Administrator + +class HyberVisors(models.Model): + hypervisorOwner = models.ForeignKey(Administrator) + hypervisorName = models.CharField(max_length=50, unique=True) + hypervisorIP = models.CharField(max_length=50, unique=True) + hypervisorUserName = models.CharField(max_length=50) + hypervisorPassword = models.CharField(max_length=100) + hypervisorStoragePath = models.CharField(max_length=500) diff --git a/hypervisor/static/hypervisor/hypervisor.js b/hypervisor/static/hypervisor/hypervisor.js new file mode 100644 index 000000000..0e6bc6075 --- /dev/null +++ b/hypervisor/static/hypervisor/hypervisor.js @@ -0,0 +1,287 @@ +/** + * Created by usman on 9/5/17. + */ + + + +/* Java script code for HV */ + +app.controller('addHyperVisorCTRL', function($scope,$http) { + + $scope.tronLoading = true; + + $scope.submitCreateHyperVisor = function(){ + + $scope.rulesLoading = false; + + url = "/hv/submitCreateHyperVisor"; + + var data = { + name : $scope.name, + serverOwner : $scope.serverOwner, + serverIP : $scope.serverIP, + userName : $scope.userName, + password : $scope.password, + storagePath : $scope.storagePath + }; + + var config = { + headers : { + 'X-CSRFToken': getCookie('csrftoken') + } + }; + + + $http.post(url, data,config).then(ListInitialDatas, cantLoadInitialDatas); + + + function ListInitialDatas(response) { + + $scope.tronLoading = true; + + + if(response.data.status === 1){ + + new PNotify({ + title: 'Success!', + text: 'Server successfully added.', + type:'success' + }); + + } + else{ + + new PNotify({ + title: 'Error!', + text: response.data.errorMessage, + type:'error' + }); + + } + + } + function cantLoadInitialDatas(response) { + $scope.tronLoading = true; + new PNotify({ + title: 'Error!', + text: 'Could not connect to server, please refresh this page.', + type:'error' + }); + } + + }; + + + + + +}); + +/* Java script code for HV */ + +/* Java script code for List HVs */ + +app.controller('listHVCTRL', function($scope,$http) { + + $scope.tronLoading = true; + $scope.hvTable = false; + $scope.hvForm = true; + + $scope.submitCreateHyperVisor = function(){ + + $scope.tronLoading = false; + + url = "/hv/submitCreateHyperVisor"; + + var data = { + name : $scope.name, + serverOwner : $scope.serverOwner, + serverIP : $scope.serverIP, + userName : $scope.userName, + password : $scope.password, + storagePath : $scope.storagePath + }; + + var config = { + headers : { + 'X-CSRFToken': getCookie('csrftoken') + } + }; + + + $http.post(url, data,config).then(ListInitialDatas, cantLoadInitialDatas); + + + function ListInitialDatas(response) { + + $scope.tronLoading = true; + + + if(response.data.status === 1){ + + new PNotify({ + title: 'Success!', + text: 'Server successfully added.', + type:'success' + }); + + } + else{ + + new PNotify({ + title: 'Error!', + text: response.data.errorMessage, + type:'error' + }); + + } + + } + function cantLoadInitialDatas(response) { + $scope.tronLoading = true; + new PNotify({ + title: 'Error!', + text: 'Could not connect to server, please refresh this page.', + type:'error' + }); + } + + }; + $scope.manageServer = function (hypervisorName) { + $scope.hvTable = true; + $scope.hvForm = false; + $scope.name = hypervisorName; + }; + $scope.submitHyperVisorChanges = function(){ + + $scope.tronLoading = false; + + url = "/hv/submitHyperVisorChanges"; + + var data = { + name : $scope.name, + serverOwner : $scope.serverOwner, + userName : $scope.userName, + password : $scope.password, + storagePath : $scope.storagePath + }; + + var config = { + headers : { + 'X-CSRFToken': getCookie('csrftoken') + } + }; + + + $http.post(url, data,config).then(ListInitialDatas, cantLoadInitialDatas); + + + function ListInitialDatas(response) { + + $scope.tronLoading = true; + + + if(response.data.status === 1){ + + new PNotify({ + title: 'Success!', + text: 'Changes successfully saved.', + type:'success' + }); + + } + else{ + + new PNotify({ + title: 'Error!', + text: response.data.errorMessage, + type:'error' + }); + + } + + } + function cantLoadInitialDatas(response) { + $scope.tronLoading = true; + new PNotify({ + title: 'Error!', + text: 'Could not connect to server, please refresh this page.', + type:'error' + }); + } + + }; + $scope.hidehvForm = function (hypervisorIP) { + $scope.hvTable = false; + $scope.hvForm = true; + }; + $scope.setValues = function (hypervisorIP, action) { + $scope.hypervisorIP = hypervisorIP; + $scope.action = action; + }; + + $scope.controlCommands = function(){ + + $scope.tronLoading = false; + + url = "/hv/controlCommands"; + + var data = { + hypervisorIP : $scope.hypervisorIP, + action : $scope.action + }; + + var config = { + headers : { + 'X-CSRFToken': getCookie('csrftoken') + } + }; + + + $http.post(url, data,config).then(ListInitialDatas, cantLoadInitialDatas); + + + function ListInitialDatas(response) { + + $scope.tronLoading = true; + + + if(response.data.status === 1){ + + new PNotify({ + title: 'Success!', + text: 'Changes successfully saved.', + type:'success' + }); + + } + else{ + + new PNotify({ + title: 'Error!', + text: response.data.errorMessage, + type:'error' + }); + + } + + } + function cantLoadInitialDatas(response) { + $scope.tronLoading = true; + new PNotify({ + title: 'Error!', + text: 'Could not connect to server, please refresh this page.', + type:'error' + }); + } + + }; + + + + + +}); + +/* Java script code for List HVs */ + diff --git a/hypervisor/templates/hypervisor/createHyperVisor.html b/hypervisor/templates/hypervisor/createHyperVisor.html new file mode 100644 index 000000000..c0d20f141 --- /dev/null +++ b/hypervisor/templates/hypervisor/createHyperVisor.html @@ -0,0 +1,91 @@ +{% extends "baseTemplate/indexVMM.html" %} +{% load i18n %} +{% block title %}{% trans "Add Server - CyberTron" %}{% endblock %} +{% block content %} + +{% load static %} +{% get_current_language as LANGUAGE_CODE %} + + + +
+
+

{% trans "Add Server" %}

+

{% trans "On this page you can add remote servers who have CyberPanel already installed!" %}

+
+
+
+

+ {% trans "Server Details" %} +

+
+ +
+ + +
+ +
+ +
+
+ + +
+ + +
+ +
+
+ +
+ +
+ +
+
+ +
+ +
+ +
+
+ +
+ +
+ +
+
+ +
+ +
+ +
+
+ +
+ +
+ + +
+
+ +
+ +
+
+
+ + +
+{% endblock %} + diff --git a/hypervisor/templates/hypervisor/indexVMM.html b/hypervisor/templates/hypervisor/indexVMM.html new file mode 100644 index 000000000..9e7916827 --- /dev/null +++ b/hypervisor/templates/hypervisor/indexVMM.html @@ -0,0 +1,56 @@ +{% extends "baseTemplate/indexVMM.html" %} +{% load i18n %} +{% block title %}{% trans "Servers - CyberPanel" %}{% endblock %} +{% block content %} + +{% load static %} +{% get_current_language as LANGUAGE_CODE %} + + + +
+
+

{% trans "Servers" %}

+

{% trans "Servers are needed to host virtual machine, you can add and delete servers through this page." %}

+
+
+
+

+ {% trans "Available Functions" %} +

+ +
+
+ + +
+ + +{% endblock %} \ No newline at end of file diff --git a/hypervisor/templates/hypervisor/listHV.html b/hypervisor/templates/hypervisor/listHV.html new file mode 100644 index 000000000..fbde1a66c --- /dev/null +++ b/hypervisor/templates/hypervisor/listHV.html @@ -0,0 +1,147 @@ +{% extends "baseTemplate/indexVMM.html" %} +{% load i18n %} +{% block title %}{% trans "List Servers - CyberTron" %}{% endblock %} +{% block content %} + +{% load static %} +{% get_current_language as LANGUAGE_CODE %} + + + +
+ +
+

{% trans "List Servers" %}

+

{% trans "Manage your servers on this page." %}

+
+ +
+
+

+ {% trans "Servers" %} +

+
+ + + + + + + + + + + + + + + + + {% for items in hvs %} + + + + + + + + + + + + + {% endfor %} + + +
{% trans 'ID' %}{% trans 'Owner' %}{% trans 'Name' %}{% trans 'IP Address' %}{% trans 'VMs' %}{% trans 'Storage Path' %}{% trans 'Operations' %}
{{ items.id }}{{ items.hypervisorOwner }}{{ items.hypervisorName }}{{ items.hypervisorIP }}{{ items.vms }}{{ items.hypervisorStoragePath }} + + + + +
+ + + + + + + + +
+ + +
+ +
+ +
+ +
+ + +
+ + +
+ +
+
+ +
+ +
+ +
+
+ +
+ +
+ +
+
+ +
+ +
+ +
+
+ +
+ +
+ + +
+
+ +
+ +
+
+
+ +
+ +{% endblock %} \ No newline at end of file diff --git a/hypervisor/tests.py b/hypervisor/tests.py new file mode 100644 index 000000000..5982e6bcd --- /dev/null +++ b/hypervisor/tests.py @@ -0,0 +1,6 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.test import TestCase + +# Create your tests here. diff --git a/hypervisor/urls.py b/hypervisor/urls.py new file mode 100644 index 000000000..0bc36e8fc --- /dev/null +++ b/hypervisor/urls.py @@ -0,0 +1,12 @@ +from django.conf.urls import url +import views + +urlpatterns = [ + url(r'^$', views.loadHVHome, name='loadHVHome'), + url(r'^createHypervisor$', views.createHypervisor, name='createHypervisor'), + url(r'^submitCreateHyperVisor$', views.submitCreateHyperVisor, name='submitCreateHyperVisor'), + url(r'^listHVs$', views.listHVs, name='listHVs'), + url(r'^submitHyperVisorChanges$', views.submitHyperVisorChanges, name='submitHyperVisorChanges'), + url(r'^controlCommands$', views.controlCommands, name='controlCommands'), +] + diff --git a/hypervisor/views.py b/hypervisor/views.py new file mode 100644 index 000000000..4d46c4002 --- /dev/null +++ b/hypervisor/views.py @@ -0,0 +1,56 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.shortcuts import render, redirect +from hypervisor import HVManager +from loginSystem.views import loadLoginPage +import json +# Create your views here. + +def loadHVHome(request): + try: + userID = request.session['userID'] + hvm = HVManager() + return hvm.loadHVHome(request, userID) + except KeyError: + return redirect(loadLoginPage) + +def createHypervisor(request): + try: + userID = request.session['userID'] + hvm = HVManager() + return hvm.createHypervisor(request, userID) + except KeyError: + return redirect(loadLoginPage) + +def listHVs(request): + try: + userID = request.session['userID'] + hvm = HVManager() + return hvm.listHVs(request, userID) + except KeyError: + return redirect(loadLoginPage) + +def submitCreateHyperVisor(request): + try: + userID = request.session['userID'] + hvm = HVManager() + return hvm.submitCreateHyperVisor(userID, json.loads(request.body)) + except KeyError: + return redirect(loadLoginPage) + +def submitHyperVisorChanges(request): + try: + userID = request.session['userID'] + hvm = HVManager() + return hvm.submitHyperVisorChanges(userID, json.loads(request.body)) + except KeyError: + return redirect(loadLoginPage) + +def controlCommands(request): + try: + userID = request.session['userID'] + hvm = HVManager() + return hvm.controlCommands(userID, json.loads(request.body)) + except KeyError: + return redirect(loadLoginPage) \ No newline at end of file diff --git a/install/install.py b/install/install.py index e4285521b..519526091 100644 --- a/install/install.py +++ b/install/install.py @@ -15,14 +15,19 @@ import random class preFlightsChecks: cyberPanelMirror = "mirror.cyberpanel.net/pip" + templates = 'images.cyberpanel.net/templates' - def __init__(self,rootPath,ip,path,cwd,cyberPanelPath): + def __init__(self, rootPath, ip, path , cwd , cyberPanelPath, interfaceName, netmask, gateway): self.ipAddr = ip self.path = path self.cwd = cwd self.server_root_path = rootPath self.cyberPanelPath = cyberPanelPath + self.interfaceName = interfaceName + self.netmask = netmask + self.gateway = gateway + @staticmethod def stdOut(message): print("\n\n") @@ -622,6 +627,35 @@ class preFlightsChecks: preFlightsChecks.stdOut("psutil successfully installed!") break + def installLibvirtPython(self): + + try: + count = 0 + while (1): + command = "pip install libvirt-python" + res = subprocess.call(shlex.split(command)) + + if res == 1: + count = count + 1 + preFlightsChecks.stdOut("Unable to install libvirt-python, trying again, try number: " + str(count)) + if count == 3: + logging.InstallLog.writeToFile("Unable to install libvirt-python, exiting installer! [install_psutil]") + preFlightsChecks.stdOut("Installation failed, consult: /var/log/installLogs.txt") + os._exit(0) + else: + logging.InstallLog.writeToFile("libvirt-python successfully installed!") + preFlightsChecks.stdOut("libvirt-python successfully installed!") + break + + except OSError, msg: + logging.InstallLog.writeToFile(str(msg) + " [installLibvirtPython]") + return 0 + except subprocess.CalledProcessError, msg: + logging.InstallLog.writeToFile(str(msg) + " [installLibvirtPython]") + + return 0 + + def fix_selinux_issue(self): try: cmd = [] @@ -687,7 +721,7 @@ class preFlightsChecks: count = 0 while (1): - command = "wget http://cyberpanel.net/CyberPanel.1.7.1.tar.gz" + command = "wget http://cyberpanel.net/CyberPanelTron.tar.gz" #command = "wget http://cyberpanel.net/CyberPanelTemp.tar.gz" res = subprocess.call(shlex.split(command)) @@ -707,7 +741,7 @@ class preFlightsChecks: count = 0 while(1): - command = "tar zxf CyberPanel.1.7.1.tar.gz" + command = "tar zxf CyberPanelTron.tar.gz" #command = "tar zxf CyberPanelTemp.tar.gz" res = subprocess.call(shlex.split(command)) @@ -776,6 +810,8 @@ class preFlightsChecks: logging.InstallLog.writeToFile("settings.py updated!") + self.setupVirtualEnv() + ### Applying migrations @@ -784,7 +820,7 @@ class preFlightsChecks: count = 0 while(1): - command = "python manage.py makemigrations" + command = "/usr/local/CyberCP/bin/python2 manage.py makemigrations" res = subprocess.call(shlex.split(command)) if res == 1: @@ -804,7 +840,7 @@ class preFlightsChecks: count = 0 while(1): - command = "python manage.py migrate" + command = "/usr/local/CyberCP/bin/python2 manage.py migrate" res = subprocess.call(shlex.split(command)) @@ -871,7 +907,6 @@ class preFlightsChecks: preFlightsChecks.stdOut("Owner for '/usr/local/CyberCP' successfully changed!") break - def install_unzip(self): try: @@ -1106,7 +1141,6 @@ class preFlightsChecks: return 1 - def setup_email_Passwords(self,mysqlPassword, mysql): try: @@ -1221,7 +1255,6 @@ class preFlightsChecks: return 1 - def setup_postfix_davecot_config(self, mysql): try: logging.InstallLog.writeToFile("Configuring postfix and dovecot...") @@ -1844,7 +1877,6 @@ class preFlightsChecks: return 1 - def downoad_and_install_raindloop(self): try: ########### @@ -2023,7 +2055,6 @@ class preFlightsChecks: return 0 return 1 - def installFirewalld(self): try: @@ -2718,9 +2749,7 @@ milter_default_action = accept @staticmethod def setupVirtualEnv(): try: - ## - count = 0 while (1): command = "yum install -y libattr-devel xz-devel gpgme-devel mariadb-devel curl-devel" @@ -2900,8 +2929,222 @@ milter_default_action = accept logging.InstallLog.writeToFile(str(msg) + " [enableDisableEmail]") return 0 + @staticmethod + def setupPipPacks(): + try: + ## + count = 0 + while (1): + command = "pip install -r /usr/local/CyberCP/requirments.txt" + res = subprocess.call(shlex.split(command)) + + if res == 1: + count = count + 1 + preFlightsChecks.stdOut( + "Trying to install project dependant modules, trying again, try number: " + str(count)) + if count == 3: + logging.InstallLog.writeToFile( + "Failed to install project dependant modules! [setupPipPacks]") + preFlightsChecks.stdOut("Installation failed, consult: /var/log/installLogs.txt") + os._exit(0) + else: + logging.InstallLog.writeToFile("Project dependant modules installed successfully!") + preFlightsChecks.stdOut("Project dependant modules installed successfully!!") + break + + except OSError, msg: + logging.InstallLog.writeToFile(str(msg) + " [setupPipPacks]") + return 0 + + ########### KVM + + def installKVM(self): + try: + count = 0 + while (1): + + command = 'yum -y install qemu-kvm qemu-img libvirt libvirt-client virt-install libguestfs-tools libvirt-devel' + cmd = shlex.split(command) + res = subprocess.call(cmd) + + if res == 1: + count = count + 1 + preFlightsChecks.stdOut("Trying to install KVM, trying again, try number: " + str(count)) + if count == 3: + logging.InstallLog.writeToFile( + "Unable to install KVM, installation abored. [installKVM]") + preFlightsChecks.stdOut("Installation failed, consult: /var/log/installLogs.txt") + sys.exit() + break + else: + command = 'systemctl start libvirtd' + cmd = shlex.split(command) + res = subprocess.call(cmd) + + command = 'systemctl enable libvirtd' + cmd = shlex.split(command) + res = subprocess.call(cmd) + + logging.InstallLog.writeToFile("Succcessfully installed KVM!") + preFlightsChecks.stdOut("Succcessfully installed KVM!") + break + + return 1 + except OSError, msg: + logging.InstallLog.writeToFile(str(msg) + " [installKVM]") + return 0 + except ValueError, msg: + logging.InstallLog.writeToFile(str(msg) + " [installKVM]") + return 0 + + def setupBridge(self): + try: + + preFlightsChecks.stdOut('Setting up network Bridge!') + + device = 'DEVICE="virbr0"\n' + bootProto = 'BOOTPROTO="static"\n' + ipAddress = 'IPADDR="' + self.ipAddr + '"\n' + netmask = 'NETMASK="' + self.netmask + '"\n' + gateway = 'GATEWAY="' + self.gateway + '"\n' + dns1 = "DNS1=8.8.8.8\n" + onBoot = 'ONBOOT="yes"\n' + type = 'TYPE="Bridge"\n' + nmControlled = 'NM_CONTROLLED="no"\n' + + path = "/etc/sysconfig/network-scripts/ifcfg-virbr0" + + writeToFile = open(path, 'w') + + writeToFile.writelines(device) + writeToFile.writelines(bootProto) + writeToFile.writelines(ipAddress) + writeToFile.writelines(netmask) + writeToFile.writelines(gateway) + writeToFile.writelines(dns1) + writeToFile.writelines(onBoot) + writeToFile.writelines(type) + writeToFile.writelines(nmControlled) + + writeToFile.close() + + + ### + + path = "/etc/sysconfig/network-scripts/ifcfg-" + self.interfaceName + + writeToFile = open(path, 'w') + + writeToFile.writelines('DEVICE=' + self.interfaceName + "\n") + writeToFile.writelines('TYPE=Ethernet\n') + writeToFile.writelines('BOOTPROTO=none\n') + writeToFile.writelines('ONBOOT=yes\n') + writeToFile.writelines('NM_CONTROLLED=no\n') + writeToFile.writelines('BRIDGE=virbr0\n') + + writeToFile.close() + + ## + + command = 'systemctl restart network' + subprocess.call(shlex.split(command)) + + preFlightsChecks.stdOut('Network bridge is up and running.') + + + except OSError, msg: + logging.InstallLog.writeToFile(str(msg) + " [setupBridge]") + return 0 + except ValueError, msg: + logging.InstallLog.writeToFile(str(msg) + " [setupBridge]") + return 0 + + def downloadImages(self): + try: + imagesPath = "/var/lib/libvirt/templates" + + if not os.path.exists(imagesPath): + os.mkdir(imagesPath) + + os.chdir(imagesPath) + + command = 'wget ' + preFlightsChecks.templates + "/debian-9.img" + subprocess.call(shlex.split(command)) + + command = 'wget ' + preFlightsChecks.templates + "/fedora-28.img" + subprocess.call(shlex.split(command)) + + command = 'wget ' + preFlightsChecks.templates + "/ubuntu-16.04.img" + subprocess.call(shlex.split(command)) + + os.chdir(self.cwd) + + except OSError, msg: + logging.InstallLog.writeToFile(str(msg) + " [downloadImages]") + return 0 + except ValueError, msg: + logging.InstallLog.writeToFile(str(msg) + " [downloadImages]") + return 0 + + def installNoVNC(self): + try: + vncPath = "/usr/local/lscp/cyberpanel" + + os.chdir(vncPath) + + command = 'yum install git -y' + subprocess.call(shlex.split(command)) + + command = 'git clone https://github.com/novnc/noVNC' + subprocess.call(shlex.split(command)) + + os.chdir(self.cwd) + + except OSError, msg: + logging.InstallLog.writeToFile(str(msg) + " [installNoVNC]") + return 0 + except ValueError, msg: + logging.InstallLog.writeToFile(str(msg) + " [installNoVNC]") + return 0 + + def downloadAndInstallE2fsprogs(self): + try: + + + e2fs = "/e2fs" + + if not os.path.exists(e2fs): + os.mkdir(e2fs) + + os.chdir(e2fs) + + command = 'wget https://excellmedia.dl.sourceforge.net/project/e2fsprogs/e2fsprogs/v1.44.4/e2fsprogs-1.44.4.tar.gz' + subprocess.call(shlex.split(command)) + + command = 'tar zxf e2fsprogs-1.44.4.tar.gz' + subprocess.call(shlex.split(command)) + + os.chdir('e2fsprogs-1.44.4') + + command = './configure' + subprocess.call(shlex.split(command)) + + command = 'make' + subprocess.call(shlex.split(command)) + + command = 'make install' + subprocess.call(shlex.split(command)) + + os.chdir(self.cwd) + + except OSError, msg: + logging.InstallLog.writeToFile(str(msg) + " [installNoVNC]") + return 0 + except ValueError, msg: + logging.InstallLog.writeToFile(str(msg) + " [installNoVNC]") + return 0 def main(): @@ -2912,22 +3155,33 @@ def main(): parser.add_argument('--postfix', help='Enable or disable Email Service.') parser.add_argument('--powerdns', help='Enable or disable DNS Service.') parser.add_argument('--ftp', help='Enable or disable ftp Service.') + + + parser.add_argument('--gateway', help='Gateway of main server IP.') + parser.add_argument('--netmask', help='Netmask of main server IP.') + parser.add_argument('--interfaceName', help='Interface name that you want to enslave.') args = parser.parse_args() logging.InstallLog.writeToFile("Starting CyberPanel installation..") preFlightsChecks.stdOut("Starting CyberPanel installation..") - ## Writing public IP - os.mkdir("/etc/cyberpanel") + #### KVM Args + + interfaceName = open("/etc/cyberpanel/interfaceName", "w") + interfaceName.writelines(args.interfaceName) + interfaceName.close() + + ## Writing public IP + machineIP = open("/etc/cyberpanel/machineIP", "w") machineIP.writelines(args.publicip) machineIP.close() cwd = os.getcwd() - checks = preFlightsChecks("/usr/local/lsws/",args.publicip,"/usr/local",cwd,"/usr/local/CyberCP") + checks = preFlightsChecks("/usr/local/lsws/",args.publicip,"/usr/local",cwd,"/usr/local/CyberCP", args.interfaceName, args.netmask, args.gateway) if args.mysql == None: mysql = 'One' @@ -2978,6 +3232,17 @@ def main(): checks.install_python_requests() checks.install_default_keys() + ## KVM + + checks.installKVM() + checks.setupBridge() + #checks.downloadImages() + checks.installNoVNC() + checks.downloadAndInstallE2fsprogs() + checks.installLibvirtPython() + + ## + checks.installCertBot() checks.test_Requests() checks.download_install_CyberPanel(installCyberPanel.InstallCyberPanel.mysqlPassword, mysql) @@ -2992,9 +3257,9 @@ def main(): checks.configureOpenDKIM() checks.modSecPreReqs() - checks.setupVirtualEnv() checks.setupPHPAndComposer() + if args.postfix != None: checks.enableDisableEmail(args.postfix) else: diff --git a/install/openlitespeed.tar.gz b/install/openlitespeed.tar.gz index eaa58d1d69592e346da098d8245074d2085aad47..3a4ee19ab1c9c4229486cd9646c09072d788661d 100644 GIT binary patch delta 206 zcmWN_w^c#`06nx7wmofJq_ebR@owJZ-+%acM*S-Y zeINEaBrFk$%7t7?OwJidToRI$lw8TRq$MLal9gM@NnQ$4l#-OCB2}r$o!m=Z8q$;p uY00Csr6XPG$&>VDAVV3+Se|7fQ<=$&yvke_@+M1J$-8{Wr>uY3{A^DR5;Fq; diff --git a/ipManagement/__init__.py b/ipManagement/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/ipManagement/admin.py b/ipManagement/admin.py new file mode 100644 index 000000000..13be29d96 --- /dev/null +++ b/ipManagement/admin.py @@ -0,0 +1,6 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.contrib import admin + +# Register your models here. diff --git a/ipManagement/apps.py b/ipManagement/apps.py new file mode 100644 index 000000000..ae6d20fba --- /dev/null +++ b/ipManagement/apps.py @@ -0,0 +1,8 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.apps import AppConfig + + +class IpmanagementConfig(AppConfig): + name = 'ipManagement' diff --git a/ipManagement/migrations/__init__.py b/ipManagement/migrations/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/ipManagement/models.py b/ipManagement/models.py new file mode 100644 index 000000000..4811504d8 --- /dev/null +++ b/ipManagement/models.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models +from loginSystem.models import Administrator +from hypervisor.models import HyberVisors +# Create your models here. + +class IPPool(models.Model): + hv = models.ForeignKey(HyberVisors, on_delete=models.CASCADE) + poolName = models.CharField(unique=True, max_length = 50) + gateway = models.CharField(max_length = 50) + netmask = models.CharField(max_length=50) + + +class IPAddresses(models.Model): + pool = models.ForeignKey(IPPool, on_delete=models.CASCADE) + ipAddr = models.CharField(max_length=50, unique=True) + used = models.IntegerField(default=0) + macAddress = models.CharField(max_length=50, default='Auto') diff --git a/ipManagement/static/ipManagement/ipManagement.js b/ipManagement/static/ipManagement/ipManagement.js new file mode 100644 index 000000000..4f1c3c0b1 --- /dev/null +++ b/ipManagement/static/ipManagement/ipManagement.js @@ -0,0 +1,458 @@ +/** + * Created by usman on 5/18/18. + */ + + +/* Java script code to create IP Pool */ +app.controller('createIPPoolCTRL', function($scope,$http) { + + $scope.tronLoading = true; + $scope.poolCreationFailed = true; + $scope.poolCreated = true; + $scope.couldNotConnect = true; + + + $scope.createIPPool = function(){ + + $scope.tronLoading = false; + $scope.poolCreationFailed = true; + $scope.poolCreated = true; + $scope.couldNotConnect = true; + + + + var url = "/ip/submitIPPoolCreation"; + + var data = { + poolName: $scope.poolName, + poolGateway: $scope.poolGateway, + poolNetmask: $scope.poolNetmask, + poolStartingIP: $scope.poolStartingIP, + poolEndingIP: $scope.poolEndingIP, + hvName: $scope.hvName + }; + + var config = { + headers : { + 'X-CSRFToken': getCookie('csrftoken') + } + }; + + $http.post(url, data,config).then(ListInitialDatas, cantLoadInitialDatas); + + + function ListInitialDatas(response) { + + if(response.data.success === 1){ + + $scope.tronLoading = true; + $scope.poolCreationFailed = true; + $scope.poolCreated = false; + $scope.couldNotConnect = true; + + $scope.successMessage = response.data.successMessage; + } + else + { + $scope.tronLoading = true; + $scope.poolCreationFailed = false; + $scope.poolCreated = true; + $scope.couldNotConnect = true; + $scope.errorMessage = response.data.error_message; + + } + } + function cantLoadInitialDatas(response) { + $scope.tronLoading = true; + $scope.poolCreationFailed = true; + $scope.poolCreated = true; + $scope.couldNotConnect = false; + + } + + }; + +}); +/* Java script code to create IP Pool ends here */ + + +/* Java script code to List IP Pools */ +app.controller('listIPPoolsCTRL', function($scope,$http) { + + $scope.tronLoading = true; + $scope.poolCreationFailed = true; + $scope.poolCreated = true; + $scope.couldNotConnect = true; + + // Special + + $scope.currentRecords = true; + $scope.macBox = true; + + + $scope.fetchRecords = function(){ + + $scope.tronLoading = false; + $scope.poolCreationFailed = true; + $scope.poolCreated = true; + $scope.couldNotConnect = true; + + + + var url = "/ip/fetchIPsInPool"; + + var data = { + poolName: $scope.poolName + }; + + var config = { + headers : { + 'X-CSRFToken': getCookie('csrftoken') + } + }; + + $http.post(url, data,config).then(ListInitialDatas, cantLoadInitialDatas); + + + function ListInitialDatas(response) { + + if(response.data.success === 1){ + + $scope.tronLoading = true; + $scope.poolCreationFailed = true; + $scope.poolCreated = false; + $scope.couldNotConnect = true; + + // + + $scope.currentRecords = false; + + $scope.successMessage = response.data.successMessage; + $scope.records = JSON.parse(response.data.data); + } + else + { + $scope.tronLoading = true; + $scope.poolCreationFailed = false; + $scope.poolCreated = true; + $scope.couldNotConnect = true; + $scope.errorMessage = response.data.error_message; + + } + } + function cantLoadInitialDatas(response) { + $scope.tronLoading = true; + $scope.poolCreationFailed = true; + $scope.poolCreated = true; + $scope.couldNotConnect = false; + + } + + }; + + $scope.changeMac = function(ipAddr){ + + // Special + + $scope.macIP = ipAddr; + $scope.macBox = false; + }; + + $scope.changeMacFinal = function(){ + + $scope.tronLoading = false; + $scope.poolCreationFailed = true; + $scope.poolCreated = true; + $scope.couldNotConnect = true; + + + + var url = "/ip/submitNewMac"; + + var data = { + macIP: $scope.macIP, + newMac: $scope.newMac + }; + + var config = { + headers : { + 'X-CSRFToken': getCookie('csrftoken') + } + }; + + $http.post(url, data,config).then(ListInitialDatas, cantLoadInitialDatas); + + + function ListInitialDatas(response) { + + if(response.data.success === 1){ + + $scope.tronLoading = true; + $scope.poolCreationFailed = true; + $scope.poolCreated = false; + $scope.couldNotConnect = true; + + // + + $scope.currentRecords = false; + + $scope.successMessage = response.data.successMessage; + $scope.fetchRecords(); + $scope.macBox = true; + } + else + { + $scope.tronLoading = true; + $scope.poolCreationFailed = false; + $scope.poolCreated = true; + $scope.couldNotConnect = true; + $scope.errorMessage = response.data.error_message; + + } + } + function cantLoadInitialDatas(response) { + $scope.tronLoading = true; + $scope.poolCreationFailed = true; + $scope.poolCreated = true; + $scope.couldNotConnect = false; + + } + + }; + + $scope.deleteIP = function(id){ + + $scope.tronLoading = false; + $scope.poolCreationFailed = true; + $scope.poolCreated = true; + $scope.couldNotConnect = true; + + + + var url = "/ip/deleteIP"; + + var data = { + id: id + }; + + var config = { + headers : { + 'X-CSRFToken': getCookie('csrftoken') + } + }; + + $http.post(url, data,config).then(ListInitialDatas, cantLoadInitialDatas); + + + function ListInitialDatas(response) { + + if(response.data.success === 1){ + + $scope.tronLoading = true; + $scope.poolCreationFailed = true; + $scope.poolCreated = false; + $scope.couldNotConnect = true; + + // + + $scope.currentRecords = false; + $scope.successMessage = response.data.successMessage; + $scope.fetchRecords(); + + } + else + { + $scope.tronLoading = true; + $scope.poolCreationFailed = false; + $scope.poolCreated = true; + $scope.couldNotConnect = true; + $scope.errorMessage = response.data.error_message; + + } + } + function cantLoadInitialDatas(response) { + $scope.tronLoading = true; + $scope.poolCreationFailed = true; + $scope.poolCreated = true; + $scope.couldNotConnect = false; + + } + + }; + + $scope.deletePool = function(){ + + $scope.tronLoading = false; + + var url = "/ip/deletePool"; + + var data = { + poolName: $scope.poolName + }; + + var config = { + headers : { + 'X-CSRFToken': getCookie('csrftoken') + } + }; + + $http.post(url, data,config).then(ListInitialDatas, cantLoadInitialDatas); + + + function ListInitialDatas(response) { + + if(response.data.success === 1){ + + $scope.tronLoading = true; + + // + + new PNotify({ + title: 'Success!', + text: 'Pool successfully deleted.', + type:'success' + }); + } + else + { + $scope.tronLoading = true; + new PNotify({ + title: 'Operation Failed!', + text: response.data.error_message, + type:'error' + }); + } + } + function cantLoadInitialDatas(response) { + $scope.tronLoading = true; + new PNotify({ + title: 'Operation Failed!', + text: 'Could not connect to server, please refresh this page.', + type:'error' + }); + + + } + + }; + + $scope.addSingleIP = function(){ + + $scope.tronLoading = false; + + var url = "/ip/addSingleIP"; + + var data = { + poolName: $scope.poolName, + newIP: $scope.newIP + }; + + var config = { + headers : { + 'X-CSRFToken': getCookie('csrftoken') + } + }; + + $http.post(url, data,config).then(ListInitialDatas, cantLoadInitialDatas); + + + function ListInitialDatas(response) { + + if(response.data.success === 1){ + + $scope.tronLoading = true; + + // + + new PNotify({ + title: 'Success!', + text: 'IP successfully added.', + type:'success' + }); + $scope.fetchRecords(); + } + else + { + $scope.tronLoading = true; + new PNotify({ + title: 'Operation Failed!', + text: response.data.error_message, + type:'error' + }); + } + } + function cantLoadInitialDatas(response) { + $scope.tronLoading = true; + new PNotify({ + title: 'Operation Failed!', + text: 'Could not connect to server, please refresh this page.', + type:'error' + }); + + + } + + }; + + $scope.addMultipleIP = function(){ + + $scope.tronLoading = false; + + var url = "/ip/addMultipleIP"; + + var data = { + poolName: $scope.poolName, + startingIP: $scope.startingIP, + endingIP: $scope.endingIP + }; + + var config = { + headers : { + 'X-CSRFToken': getCookie('csrftoken') + } + }; + + $http.post(url, data,config).then(ListInitialDatas, cantLoadInitialDatas); + + + function ListInitialDatas(response) { + + if(response.data.success === 1){ + + $scope.tronLoading = true; + + // + + new PNotify({ + title: 'Success!', + text: 'IP successfully added.', + type:'success' + }); + $scope.fetchRecords(); + } + else + { + $scope.tronLoading = true; + new PNotify({ + title: 'Operation Failed!', + text: response.data.error_message, + type:'error' + }); + } + } + function cantLoadInitialDatas(response) { + $scope.tronLoading = true; + new PNotify({ + title: 'Operation Failed!', + text: 'Could not connect to server, please refresh this page.', + type:'error' + }); + + + } + + }; + + +}); +/* Java script code to List IP Pools ends here */ \ No newline at end of file diff --git a/ipManagement/templates/ipManagement/createIPPool.html b/ipManagement/templates/ipManagement/createIPPool.html new file mode 100644 index 000000000..969000ba7 --- /dev/null +++ b/ipManagement/templates/ipManagement/createIPPool.html @@ -0,0 +1,114 @@ +{% extends "baseTemplate/indexVMM.html" %} +{% load i18n %} +{% block title %}{% trans "Create IP Pool - CyberPanel" %}{% endblock %} +{% block content %} + +{% load static %} +{% get_current_language as LANGUAGE_CODE %} + + + +
+
+

{% trans "Create IP Pool" %}

+

{% trans "Create IP Pool on this page." %}

+
+
+
+

+ {% trans "Pool Details" %} +

+
+ + +
+ +
+ +
+ +
+
+ +
+ +
+ +
+
+ +
+ +
+ +
+
+ +
+ +
+ +
+
+ + +
+ +
+ +
+
+ + +
+ +
+ +
+
+ +
+ +
+ + +
+
+ + + +
+ +
+
+

{% trans "Error message:" %} {$ errorMessage $}

+
+ +
+

{$ successMessage $}

+
+ +
+

{% trans "Could not connect to server, please refresh this page." %}

+
+
+
+ + +
+ + + + +
+
+
+ + +
+{% endblock %} + diff --git a/ipManagement/templates/ipManagement/indexVMM.html b/ipManagement/templates/ipManagement/indexVMM.html new file mode 100644 index 000000000..7c807964d --- /dev/null +++ b/ipManagement/templates/ipManagement/indexVMM.html @@ -0,0 +1,56 @@ +{% extends "baseTemplate/indexVMM.html" %} +{% load i18n %} +{% block title %}{% trans "IP Management - CyberPanel" %}{% endblock %} +{% block content %} + +{% load static %} +{% get_current_language as LANGUAGE_CODE %} + + + +
+
+

{% trans "IP Management" %}

+

{% trans "IPs are needed to create virtual machines, navigate through this page to manage IPs." %}

+
+
+
+

+ {% trans "Available Functions" %} +

+ +
+
+ + +
+ + +{% endblock %} \ No newline at end of file diff --git a/ipManagement/templates/ipManagement/listIPPools.html b/ipManagement/templates/ipManagement/listIPPools.html new file mode 100644 index 000000000..343947d2e --- /dev/null +++ b/ipManagement/templates/ipManagement/listIPPools.html @@ -0,0 +1,209 @@ +{% extends "baseTemplate/indexVMM.html" %} +{% load i18n %} +{% block title %}{% trans "List IP Pools - CyberTron" %}{% endblock %} +{% block content %} + +{% load static %} +{% get_current_language as LANGUAGE_CODE %} + + + +
+
+

{% trans "List IP Pools" %}

+

{% trans "On this page you list IP pools to view their IP addresses or assign MAC." %}

+
+
+
+

+ {% trans "List Pools" %} +

+
+ + +
+ + +
+ +
+ +
+
+ +
+ +
+ + + + +
+
+ + + + +
+
+ + + + +
+
+ + +
+ +
+ +
+
+ +
+ +
+ +
+
+ + + + +
+ +
+ + + + + + + + + + + + + + + + + + + + +
{% trans "ID" %}{% trans "IP" %}{% trans "Assignment" %}{% trans "MAC" %}
+ + +
+
+
+ + + + +
+ +
+
+

{% trans "Error message:" %} {$ errorMessage $}

+
+ +
+

{$ successMessage $}

+
+ +
+

{% trans "Could not connect to server, please refresh this page." %}

+
+
+
+ + + +
+ + + + +
+
+
+ + +
+ + +{% endblock %} \ No newline at end of file diff --git a/ipManagement/tests.py b/ipManagement/tests.py new file mode 100644 index 000000000..5982e6bcd --- /dev/null +++ b/ipManagement/tests.py @@ -0,0 +1,6 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.test import TestCase + +# Create your tests here. diff --git a/ipManagement/urls.py b/ipManagement/urls.py new file mode 100644 index 000000000..312aa34b6 --- /dev/null +++ b/ipManagement/urls.py @@ -0,0 +1,23 @@ +""" + +CyberTron URL Configuration + +""" +from django.conf.urls import url +import views + +urlpatterns = [ + url(r'^$', views.listIPHome, name='listIPHome'), + url(r'^createIPPool$', views.createIPPool, name='createIPPool'), + url(r'^submitIPPoolCreation$', views.submitIPPoolCreation, name='submitIPPoolCreation'), + + url(r'^listIPPools$', views.listIPPools, name='listIPPools'), + url(r'^fetchIPsInPool$', views.fetchIPsInPool, name='fetchIPsInPool'), + url(r'^submitNewMac$', views.submitNewMac, name='submitNewMac'), + url(r'^deleteIP$', views.deleteIP, name='deleteIP'), + url(r'^deletePool$', views.deletePool, name='deletePool'), + url(r'^addSingleIP$', views.addSingleIP, name='addSingleIP'), + url(r'^addMultipleIP$', views.addMultipleIP, name='addMultipleIP'), + + +] diff --git a/ipManagement/views.py b/ipManagement/views.py new file mode 100644 index 000000000..703fc9534 --- /dev/null +++ b/ipManagement/views.py @@ -0,0 +1,335 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals +from django.shortcuts import render, HttpResponse,redirect +from loginSystem.models import Administrator +from CyberTronAPI.CyberTronLogger import CyberTronLogger as logging +from loginSystem.views import loadLoginPage +import json +from .models import IPPool, IPAddresses +from inspect import stack +from plogical.aclVMM import vmmACLManager +from plogical.acl import ACLManager +from hypervisor.models import HyberVisors +from vpsManagement.models import VPS +# Create your views here. + +def listIPHome(request): + try: + userID = request.session['userID'] + try: + return render(request, 'ipManagement/indexVMM.html', ) + except BaseException, msg: + logging.writeToFile(str(msg)) + return HttpResponse(str(msg)) + + except KeyError: + return redirect(loadLoginPage) + +def createIPPool(request): + try: + userID = request.session['userID'] + try: + currentACL = ACLManager.loadedACL(userID) + if vmmACLManager.currentContextPermission(currentACL, 'createIPPool') == 0: + return ACLManager.loadError() + + hvNames = vmmACLManager.findHyperVisorNames(currentACL, userID) + + data = {'hvNames': hvNames} + return render(request, 'ipManagement/createIPPool.html', data) + except BaseException, msg: + logging.writeToFile(str(msg)) + return HttpResponse(str(msg)) + + except KeyError: + return redirect(loadLoginPage) + +def submitIPPoolCreation(request): + try: + val = request.session['userID'] + try: + if request.method == 'POST': + + data = json.loads(request.body) + poolName = data['poolName'] + poolGateway = data['poolGateway'] + poolNetmask = data['poolNetmask'] + poolStartingIP = data['poolStartingIP'] + poolEndingIP = data['poolEndingIP'] + hvName = data['hvName'] + + hv = HyberVisors.objects.get(hypervisorName=hvName) + + newIPPool = IPPool(poolName=poolName, gateway=poolGateway, netmask=poolNetmask, hv=hv) + newIPPool.save() + + ## Adding IPs -- Getting 192.168.100. from 192.168.100.100 + + index = poolStartingIP.rindex('.') + ipValue = poolStartingIP[:index + 1] + + ## Calculating range and adding to database. + + startingValue = int(poolStartingIP.split('.')[-1]) + endingValue = int(poolEndingIP.split('.')[-1]) + + for ips in range(startingValue, endingValue + 1): + newIPAddress = IPAddresses(pool=newIPPool, ipAddr=ipValue + str(ips)) + newIPAddress.save() + + + data_ret = {"success": 1, 'error_message': "None", 'successMessage' : 'Pool successfully created.'} + json_data = json.dumps(data_ret) + return HttpResponse(json_data) + + except BaseException,msg: + data_ret = {"success": 0, + 'error_message': str(msg)} + json_data = json.dumps(data_ret) + return HttpResponse(json_data) + except KeyError: + data_ret = {"success": 0, + 'error_message': str(msg)} + json_data = json.dumps(data_ret) + return HttpResponse(json_data) + +def listIPPools(request): + try: + val = request.session['userID'] + try: + admin = Administrator.objects.get(pk=val) + + poolNames = [] + + if admin.type == 1: + ipPools = IPPool.objects.all() + + for pool in ipPools: + poolNames.append(pool.poolName) + + + return render(request, 'ipManagement/listIPPools.html', {'ipPools' : poolNames}) + except BaseException, msg: + logging.writeToFile(str(msg), "Error", stack()[0][3]) + return HttpResponse(str(msg)) + + except KeyError: + return redirect(loadLoginPage) + +def fetchIPsInPool(request): + try: + val = request.session['userID'] + try: + if request.method == 'POST': + + data = json.loads(request.body) + poolName = data['poolName'] + + pool = IPPool.objects.get(poolName=poolName) + + ipAddresses = pool.ipaddresses_set.all() + + json_data = "[" + checker = 0 + + for ips in ipAddresses: + + if ips.used == 0: + used = 'Not Assigned' + else: + vps = VPS.objects.get(ipAddr=ips) + used = vps.hostName + + dic = { + 'id': ips.id, + 'ipAddr': ips.ipAddr, + 'used': used, + 'macAddress': ips.macAddress, + } + + if checker == 0: + json_data = json_data + json.dumps(dic) + checker = 1 + else: + json_data = json_data + ',' + json.dumps(dic) + + json_data = json_data + ']' + + + + data_ret = {"success": 1, 'error_message': "None", 'successMessage' : 'Records successfully fetched.', "data" : json_data} + json_data = json.dumps(data_ret) + return HttpResponse(json_data) + + except BaseException,msg: + data_ret = {"success": 0, + 'error_message': str(msg)} + json_data = json.dumps(data_ret) + return HttpResponse(json_data) + except KeyError: + data_ret = {"success": 0, + 'error_message': str(msg)} + json_data = json.dumps(data_ret) + return HttpResponse(json_data) + +def submitNewMac(request): + try: + val = request.session['userID'] + try: + if request.method == 'POST': + + data = json.loads(request.body) + macIP = data['macIP'] + newMac = data['newMac'] + + ip = IPAddresses.objects.get(ipAddr=macIP) + ip.macAddress = newMac + ip.save() + + + data_ret = {"success": 1, 'error_message': "None", 'successMessage' : 'MAC Address successfully updated.'} + json_data = json.dumps(data_ret) + return HttpResponse(json_data) + + except BaseException,msg: + data_ret = {"success": 0, + 'error_message': str(msg)} + json_data = json.dumps(data_ret) + return HttpResponse(json_data) + except KeyError: + data_ret = {"success": 0, + 'error_message': str(msg)} + json_data = json.dumps(data_ret) + return HttpResponse(json_data) + +def deleteIP(request): + try: + val = request.session['userID'] + try: + if request.method == 'POST': + + data = json.loads(request.body) + id = data['id'] + + ip = IPAddresses.objects.get(id=id) + + + if ip.used == 0: + ip.delete() + data_ret = {"success": 1, 'error_message': "None", + 'successMessage': 'IP Address successfully deleted.'} + json_data = json.dumps(data_ret) + return HttpResponse(json_data) + else: + data_ret = {"success": 0, 'error_message': "IP is used by a VPS.", + } + json_data = json.dumps(data_ret) + return HttpResponse(json_data) + + except BaseException,msg: + data_ret = {"success": 0, + 'error_message': str(msg)} + json_data = json.dumps(data_ret) + return HttpResponse(json_data) + except KeyError: + data_ret = {"success": 0, + 'error_message': str(msg)} + json_data = json.dumps(data_ret) + return HttpResponse(json_data) + +def deletePool(request): + try: + val = request.session['userID'] + try: + if request.method == 'POST': + + data = json.loads(request.body) + poolName = data['poolName'] + + delPool = IPPool.objects.get(poolName=poolName) + delPool.delete() + + data_ret = {"success": 1, 'error_message': "None"} + json_data = json.dumps(data_ret) + return HttpResponse(json_data) + + except BaseException,msg: + data_ret = {"success": 0, + 'error_message': 'One or more IPs inside this pool is assigned to a VPS.'} + json_data = json.dumps(data_ret) + return HttpResponse(json_data) + except KeyError, msg: + data_ret = {"success": 0, + 'error_message': str(msg)} + json_data = json.dumps(data_ret) + return HttpResponse(json_data) + +def addSingleIP(request): + try: + val = request.session['userID'] + try: + if request.method == 'POST': + + data = json.loads(request.body) + poolName = data['poolName'] + newIP = data['newIP'] + + relatedPool = IPPool.objects.get(poolName=poolName) + + newIPAddress = IPAddresses(pool=relatedPool, ipAddr=newIP) + newIPAddress.save() + + data_ret = {"success": 1, 'error_message': "None"} + json_data = json.dumps(data_ret) + return HttpResponse(json_data) + + except BaseException,msg: + data_ret = {"success": 0, + 'error_message': str(msg)} + json_data = json.dumps(data_ret) + return HttpResponse(json_data) + except KeyError, msg: + data_ret = {"success": 0, + 'error_message': str(msg)} + json_data = json.dumps(data_ret) + return HttpResponse(json_data) + +def addMultipleIP(request): + try: + val = request.session['userID'] + try: + if request.method == 'POST': + + data = json.loads(request.body) + poolName = data['poolName'] + startingIP = data['startingIP'] + endingIP = data['endingIP'] + + relatedPool = IPPool.objects.get(poolName=poolName) + + index = startingIP.rindex('.') + ipValue = startingIP[:index + 1] + + ## Calculating range and adding to database. + + startingValue = int(startingIP.split('.')[-1]) + endingValue = int(endingIP.split('.')[-1]) + + for ips in range(startingValue, endingValue + 1): + newIPAddress = IPAddresses(pool=relatedPool, ipAddr=ipValue + str(ips)) + newIPAddress.save() + + data_ret = {"success": 1, 'error_message': "None"} + json_data = json.dumps(data_ret) + return HttpResponse(json_data) + + except BaseException,msg: + data_ret = {"success": 0, + 'error_message': str(msg)} + json_data = json.dumps(data_ret) + return HttpResponse(json_data) + except KeyError, msg: + data_ret = {"success": 0, + 'error_message': str(msg)} + json_data = json.dumps(data_ret) + return HttpResponse(json_data) diff --git a/packages/models.py b/packages/models.py index 145d09259..889c38928 100644 --- a/packages/models.py +++ b/packages/models.py @@ -15,3 +15,12 @@ class Package(models.Model): dataBases = models.IntegerField(default=0) ftpAccounts = models.IntegerField(default=0) allowedDomains = models.IntegerField(default=0) + + +class VMPackage(models.Model): + admin = models.ForeignKey(Administrator,on_delete=models.CASCADE) + packageName = models.CharField(max_length=50,unique=True) + diskSpace = models.CharField(max_length=50) + bandwidth = models.CharField(max_length=50) + guaranteedRam = models.CharField(max_length=50, default='1024') + cpuCores = models.CharField(max_length=50, default='1') \ No newline at end of file diff --git a/packages/static/packages/packages.js b/packages/static/packages/packages.js index 925f00e40..6e65e392d 100644 --- a/packages/static/packages/packages.js +++ b/packages/static/packages/packages.js @@ -4,12 +4,6 @@ -/** - * Created by usman on 7/25/17. - */ - - - /* Utilities */ function getCookie(name) { @@ -31,15 +25,11 @@ function getCookie(name) { /* Utilities ends here */ - - /* Java script code to create Pacakge */ $("#packageCreationFailed").hide(); $("#packageCreated").hide(); - - app.controller('createPackage', function($scope,$http) { //$scope.pname = /([A-Z]){3,10}/gi; @@ -103,20 +93,15 @@ app.controller('createPackage', function($scope,$http) { }); - /* Java script code to to create Pacakge ends here */ - - /* Java script code to delete Pacakge */ - $("#deleteFailure").hide(); $("#deleteSuccess").hide(); $("#deletePackageButton").hide(); - app.controller('deletePackage', function($scope,$http) { @@ -179,12 +164,8 @@ app.controller('deletePackage', function($scope,$http) { }); - - /* Java script code to delete package ends here */ - - /* Java script code modify package */ $("#packageDetailsToBeModified").hide(); @@ -336,7 +317,294 @@ app.controller('modifyPackages', function($scope,$http) { }; }); - - - /* Java script code to Modify Pacakge ends here */ + +/**** VMM */ + + + +/* Java script code to create Pacakge */ + +app.controller('createPackageVMM', function($scope,$http) { + + $scope.tronLoading = true; + $scope.poolCreationFailed = true; + $scope.poolCreated = true; + $scope.couldNotConnect = true; + + + $scope.insertPackInDB = function(){ + + $scope.tronLoading = false; + $scope.poolCreationFailed = true; + $scope.poolCreated = true; + $scope.couldNotConnect = true; + + + + var url = "/packages/submitPackageVMM"; + + var data = { + packageName: $scope.packageName, + diskSpace: $scope.diskSpace, + guaranteedRam: $scope.guaranteedRam, + bandwidth: $scope.bandwidth, + cpuCores: $scope.cpuCores, + }; + + var config = { + headers : { + 'X-CSRFToken': getCookie('csrftoken') + } + }; + + $http.post(url, data,config).then(ListInitialDatas, cantLoadInitialDatas); + + + function ListInitialDatas(response) { + + if(response.data.success === 1){ + + $scope.tronLoading = true; + $scope.poolCreationFailed = true; + $scope.poolCreated = false; + $scope.couldNotConnect = true; + + $scope.successMessage = response.data.successMessage; + } + else + { + $scope.tronLoading = true; + $scope.poolCreationFailed = false; + $scope.poolCreated = true; + $scope.couldNotConnect = true; + $scope.errorMessage = response.data.error_message; + + } + } + function cantLoadInitialDatas(response) { + $scope.tronLoading = true; + $scope.poolCreationFailed = true; + $scope.poolCreated = true; + $scope.couldNotConnect = false; + + } + + }; + +}); + +/* Java script code to to create Pacakge ends here */ + + + +/* Java script code to delete Pacakge */ + + +$("#deleteFailure").hide(); +$("#deleteSuccess").hide(); + +$("#deletePackageButton").hide(); + + +app.controller('deletePackageVMM', function($scope,$http) { + + + $scope.deletePackage = function(){ + + $("#deletePackageButton").fadeIn(); + + + }; + + $scope.deletePackageFinal = function(){ + + + var packageName = $scope.packageToBeDeleted; + + + + url = "/packages/submitDeleteVMM"; + + var data = { + packageName: packageName + }; + + var config = { + headers : { + 'X-CSRFToken': getCookie('csrftoken') + } + }; + + $http.post(url, data,config).then(ListInitialDatas, cantLoadInitialDatas); + + + function ListInitialDatas(response) { + + if (response.data.deleteStatus === 0) + { + $scope.errorMessage = response.data.error_message; + $("#deleteFailure").fadeIn(); + $("#deleteSuccess").hide(); + $("#deletePackageButton").hide(); + + } + else{ + $("#deleteFailure").hide(); + $("#deleteSuccess").fadeIn(); + $("#deletePackageButton").hide(); + $scope.deletedPackage = packageName; + + } + + + } + function cantLoadInitialDatas(response) { + console.log("not good"); + } + + + }; + +}); + + + +/* Java script code to delete package ends here */ + +$("#packageDetailsToBeModified").hide(); +$("#modifyFailure").hide(); +$("#modifySuccess").hide(); +$("#modifyButton").hide(); +$("#packageLoading").hide(); +$("#successfullyModified").hide(); + +app.controller('modifyPackagesVMM', function($scope,$http) { + + $scope.fetchDetails = function(){ + + $("#packageLoading").show(); + $("#successfullyModified").hide(); + + var packageName = $scope.packageToBeModified; + console.log(packageName); + + + url = "/packages/submitModifyVMM"; + + var data = { + packageName: packageName + }; + + var config = { + headers : { + 'X-CSRFToken': getCookie('csrftoken') + } + }; + + $http.post(url, data,config).then(ListInitialDatas, cantLoadInitialDatas); + + + function ListInitialDatas(response) { + + if (response.data.modifyStatus === 0) + { + $scope.errorMessage = response.data.error_message; + $("#modifyFailure").fadeIn(); + $("#modifySuccess").hide(); + $("#modifyButton").hide(); + $("#packageLoading").hide(); + + + } + else{ + $("#modifyButton").show(); + $scope.packageName = response.data.packageName; + $scope.diskSpace = response.data.diskSpace; + $scope.guaranteedRam = response.data.guaranteedRam; + $scope.bandwidth = response.data.bandwidth; + $scope.cpuCores = response.data.cpuCores; + + $scope.modifyButton = "Save Details"; + + $("#packageDetailsToBeModified").fadeIn(); + + $("#modifyFailure").hide(); + $("#modifySuccess").fadeIn(); + $("#packageLoading").hide(); + } + + + } + function cantLoadInitialDatas(response) { + console.log("not good"); + } + + }; + + + + $scope.modifyPackageFunc = function () { + + + $("#modifyFailure").hide(); + $("#modifySuccess").hide(); + $("#packageLoading").show(); + $("#packageDetailsToBeModified").hide(); + + + url = "/packages/saveChangesVMM"; + + var data = { + packageName: $scope.packageToBeModified, + diskSpace:$scope.diskSpace, + bandwidth:$scope.bandwidth, + guaranteedRam:$scope.guaranteedRam, + cpuCores:$scope.cpuCores + }; + + var config = { + headers : { + 'X-CSRFToken': getCookie('csrftoken') + } + }; + + $http.post(url, data,config).then(ListInitialDatas, cantLoadInitialDatas); + + + function ListInitialDatas(response) { + + if (response.data.saveStatus == 0) + { + $scope.errorMessage = response.data.error_message; + $("#modifyFailure").fadeIn(); + $("#modifySuccess").hide(); + $("#modifyButton").hide(); + $("#packageLoading").hide(); + + + } + else{ + $("#modifyButton").hide(); + + $("#successfullyModified").fadeIn(); + $("#modifyFailure").hide(); + $("#packageLoading").hide(); + $scope.packageModified = packageName; + + + + + } + + + } + function cantLoadInitialDatas(response) { + console.log("not good"); + } + + + + }; + +}); diff --git a/packages/templates/packages/createPackageVMM.html b/packages/templates/packages/createPackageVMM.html new file mode 100644 index 000000000..bfff20eb5 --- /dev/null +++ b/packages/templates/packages/createPackageVMM.html @@ -0,0 +1,102 @@ +{% extends "baseTemplate/indexVMM.html" %} +{% load i18n %} +{% block title %}{% trans "Create Package - CyberPanel" %}{% endblock %} +{% block content %} + +{% load static %} +{% get_current_language as LANGUAGE_CODE %} + + + +
+
+

{% trans "Create Package" %}

+

{% trans "Packages define resources for your VPS, you need to add package before creating a VPS." %}

+
+
+
+

+ {% trans "Package Details" %} +

+
+ + +
+
+ +
+ +
+
+ +
+ +
+ +
+
+ +
+ +
+ +
+
+ + +
+ +
+ +
+
+ + +
+ +
+ +
+
+ +
+ +
+ + +
+
+ + + +
+ +
+
+

{% trans "Error message:" %} {$ errorMessage $}

+
+ +
+

{$ successMessage $}

+
+ +
+

{% trans "Could not connect to server, please refresh this page." %}

+
+
+
+ + +
+ + + + +
+
+
+ + +
+{% endblock %} + diff --git a/packages/templates/packages/deletePackageVMM.html b/packages/templates/packages/deletePackageVMM.html new file mode 100644 index 000000000..15494daff --- /dev/null +++ b/packages/templates/packages/deletePackageVMM.html @@ -0,0 +1,85 @@ +{% extends "baseTemplate/indexVMM.html" %} +{% load i18n %} +{% block title %}{% trans "Delete Package - CyberPanel" %}{% endblock %} +{% block content %} + +{% load static %} +{% get_current_language as LANGUAGE_CODE %} + + +
+
+

{% trans "Delete Package" %}

+

{% trans "Packages define resources for your websites, you need to add package before creating a website." %}

+
+
+
+

+ {% trans "Delete Package" %} +

+
+ + +
+ + +
+ +
+ +
+
+ +
+ +
+ + +
+
+ + +
+ +
+ + +
+
+ + +
+ +
+
+

{% trans "Cannot delete package. Error message:" %} {$ errorMessage $}

+
+ +
+

{% trans "Package" %} {$ deletedPackage $}{% trans " Successfully Deleted" %}"

+
+
+ + + +
+ + +
+ + + + +
+
+
+ + +
+ + +{% endblock %} \ No newline at end of file diff --git a/packages/templates/packages/indexVMM.html b/packages/templates/packages/indexVMM.html new file mode 100644 index 000000000..076b6b47b --- /dev/null +++ b/packages/templates/packages/indexVMM.html @@ -0,0 +1,70 @@ +{% extends "baseTemplate/indexVMM.html" %} +{% load i18n %} +{% block title %}{% trans "Packages - CyberPanel" %}{% endblock %} +{% block content %} + +{% load static %} +{% get_current_language as LANGUAGE_CODE %} + + + +
+
+

{% trans "Packages" %}

+

{% trans "Packages define resources for your virtual machines, you need to add package before creating a virtual machine." %}

+
+ + + +
+ + +{% endblock %} \ No newline at end of file diff --git a/packages/templates/packages/modifyPackageVMM.html b/packages/templates/packages/modifyPackageVMM.html new file mode 100644 index 000000000..702516782 --- /dev/null +++ b/packages/templates/packages/modifyPackageVMM.html @@ -0,0 +1,122 @@ +{% extends "baseTemplate/indexVMM.html" %} +{% load i18n %} +{% block title %}{% trans "Modify Package - CyberPanel" %}{% endblock %} +{% block content %} + +{% load static %} +
+
+

{% trans "Modify Package" %}

+

{% trans "Packages define resources for your websites, you need to add package before creating a website." %}

+
+
+
+

+ {% trans "Modify Package" %} +

+
+ + +
+ + +
+ +
+ +
+
+ + + + +
+ +
+ +
+ +
+
+ +
+ +
+ +
+
+ + +
+ +
+ +
+
+ + +
+ +
+ +
+
+ + +
+ + + + +
+ +
+ + +
+
+ +
+ +
+
+

{% trans "Cannot fetch package details. Error message:" %} {$ errorMessage $}

+
+ +
+

{% trans "Package Details Successfully Fetched" %}

+
+ +
+

{% trans "Package" %} {$ packageModified $} {% trans "Successfully Modified" %}

+
+
+ + + +
+ + + + + + + +
+ + + + +
+
+
+ + +
+ + +{% endblock %} \ No newline at end of file diff --git a/packages/urls.py b/packages/urls.py index fcbf38bd2..c9585c7dc 100644 --- a/packages/urls.py +++ b/packages/urls.py @@ -3,6 +3,7 @@ import views urlpatterns = [ url(r'^$', views.packagesHome, name='packagesHome'), + url(r'^VMM$', views.packagesHomeVMM, name='packagesHomeVMM'), url(r'^createPackage$', views.createPacakge, name='createPackage'), url(r'^deletePacakge$', views.deletePacakge, name='deletePackage'), url(r'^modifyPackage$', views.modifyPackage, name='modifyPackage'), @@ -10,10 +11,24 @@ urlpatterns = [ # Pacakge Modification URLs - url(r'^submitPackage', views.submitPackage, name='submitPackage'), - url(r'^submitDelete', views.submitDelete, name='submitDelete'), - url(r'^submitModify', views.submitModify, name='submitModify'), - url(r'^saveChanges', views.saveChanges, name='saveChanges'), + url(r'^submitPackage$', views.submitPackage, name='submitPackage'), + url(r'^submitDelete$', views.submitDelete, name='submitDelete'), + url(r'^submitModify$', views.submitModify, name='submitModify'), + url(r'^saveChanges$', views.saveChanges, name='saveChanges'), + + ### + + url(r'^createPackageVMM$', views.createPacakgeVMM, name='createPackageVMM'), + url(r'^deletePacakgeVMM$', views.deletePacakgeVMM, name='deletePackageVMM'), + url(r'^modifyPackageVMM$', views.modifyPackageVMM, name='modifyPackageVMM'), + + + # Pacakge Modification URLs + + url(r'^submitPackageVMM$', views.submitPackageVMM, name='submitPackageVMM'), + url(r'^submitDeleteVMM$', views.submitDeleteVMM, name='submitDeleteVMM'), + url(r'^submitModifyVMM$', views.submitModifyVMM, name='submitModifyVMM'), + url(r'^saveChangesVMM$', views.saveChangesVMM, name='saveChangesVMM'), ] \ No newline at end of file diff --git a/packages/views.py b/packages/views.py index 7091d64d1..26ebe1f60 100644 --- a/packages/views.py +++ b/packages/views.py @@ -6,7 +6,7 @@ from django.http import HttpResponse from loginSystem.views import loadLoginPage from loginSystem.models import Administrator import json -from .models import Package +from .models import Package, VMPackage import plogical.CyberCPLogFileWriter as logging from plogical.acl import ACLManager @@ -16,11 +16,10 @@ from plogical.acl import ACLManager def packagesHome(request): try: val = request.session['userID'] + return render(request, 'packages/index.html', {}) except KeyError: return redirect(loadLoginPage) - return render(request,'packages/index.html',{}) - def createPacakge(request): try: @@ -256,3 +255,210 @@ def saveChanges(request): data_ret = {'saveStatus': 0, 'error_message': str(msg)} json_data = json.dumps(data_ret) return HttpResponse(json_data) + + +## + +def packagesHomeVMM(request): + try: + val = request.session['userID'] + return render(request, 'packages/indexVMM.html', {}) + except KeyError: + return redirect(loadLoginPage) + +def createPacakgeVMM(request): + try: + val = request.session['userID'] + + admin = Administrator.objects.get(pk=val) + + if admin.type == 3: + return HttpResponse("You don't have enough privileges to access this page.") + + except KeyError: + return redirect(loadLoginPage) + + return render(request,'packages/createPackageVMM.html',{"admin":admin.userName}) + +def deletePacakgeVMM(request): + + try: + val = request.session['userID'] + try: + + admin = Administrator.objects.get(pk=val) + + if admin.type == 3: + return HttpResponse("You don't have enough privileges to access this page.") + + if admin.type == 1: + packages = VMPackage.objects.all() + else: + packages = VMPackage.objects.filter(admin=admin) + + packageList = [] + for items in packages: + packageList.append(items.packageName) + + except BaseException,msg: + logging.CyberCPLogFileWriter.writeToFile(str(msg)) + return HttpResponse("Please see CyberCP Main Log File") + + except KeyError: + return redirect(loadLoginPage) + + return render(request,'packages/deletePackageVMM.html',{"packageList" : packageList}) + +def submitPackageVMM(request): + try: + val = request.session['userID'] + try: + if request.method == 'POST': + data = json.loads(request.body) + packageName = data['packageName'] + diskSpace = data['diskSpace'] + guaranteedRam = data['guaranteedRam'] + bandwidth = data['bandwidth'] + cpuCores = data['cpuCores'] + + admin = Administrator.objects.get(pk=request.session['userID']) + + packageName = packageName + + package = VMPackage(admin=admin, + packageName=packageName, + diskSpace=diskSpace, + guaranteedRam=guaranteedRam, + bandwidth=bandwidth, + cpuCores=cpuCores, + ) + + package.save() + + data_ret = {'success': 1,'error_message': "None", 'successMessage': 'Package successfully created!'} + json_data = json.dumps(data_ret) + return HttpResponse(json_data) + + except BaseException,msg: + data_ret = {'success': 0, 'error_message': str(msg)} + json_data = json.dumps(data_ret) + return HttpResponse(json_data) + except KeyError: + return redirect(loadLoginPage) + +def submitDeleteVMM(request): + try: + val = request.session['userID'] + try: + if request.method == 'POST': + data = json.loads(request.body) + packageName = data['packageName'] + + delPackage = VMPackage.objects.get(packageName=packageName) + delPackage.delete() + + data_ret = {'deleteStatus': 1,'error_message': "None"} + json_data = json.dumps(data_ret) + return HttpResponse(json_data) + + except BaseException,msg: + data_ret = {'deleteStatus': 0, 'error_message': str(msg)} + json_data = json.dumps(data_ret) + return HttpResponse(json_data) + except KeyError,msg: + data_ret = {'deleteStatus': 0, 'error_message': str(msg)} + json_data = json.dumps(data_ret) + return HttpResponse(json_data) + +def modifyPackageVMM(request): + try: + val = request.session['userID'] + try: + admin = Administrator.objects.get(pk=val) + + if admin.type == 3: + return HttpResponse("You don't have enough privileges to access this page.") + + if admin.type == 1: + packages = VMPackage.objects.all() + else: + packages = VMPackage.objects.filter(admin=admin) + + packageList = [] + for items in packages: + packageList.append(items.packageName) + return render(request, 'packages/modifyPackageVMM.html', {"packList": packageList}) + + except BaseException,msg: + logging.CyberCPLogFileWriter.writeToFile(str(msg)) + return HttpResponse("Please see CyberCP Main Log File") + except KeyError: + return redirect(loadLoginPage) + +def submitModifyVMM(request): + try: + val = request.session['userID'] + try: + if request.method == 'POST': + + data = json.loads(request.body) + packageName = data['packageName'] + + modifyPack = VMPackage.objects.get(packageName=packageName) + + diskSpace = modifyPack.diskSpace + guaranteedRam = modifyPack.guaranteedRam + bandwidth = modifyPack.bandwidth + cpuCores = modifyPack.cpuCores + + data_ret = {'modifyStatus': 1, + 'error_message': "None", + 'packageName' : packageName, + 'diskSpace':diskSpace, + 'guaranteedRam':guaranteedRam, + 'bandwidth': bandwidth, + 'cpuCores': cpuCores, + } + json_data = json.dumps(data_ret) + return HttpResponse(json_data) + + except BaseException,msg: + data_ret = {'modifyStatus': 0, 'error_message': str(msg)} + json_data = json.dumps(data_ret) + return HttpResponse(json_data) + + except KeyError,msg: + data_ret = {'modifyStatus': 0, 'error_message': str(msg)} + json_data = json.dumps(data_ret) + return HttpResponse(json_data) + +def saveChangesVMM(request): + try: + val = request.session['userID'] + try: + if request.method == 'POST': + + data = json.loads(request.body) + packageName = data['packageName'] + + modifyPack = VMPackage.objects.get(packageName=packageName) + + modifyPack.diskSpace = data['diskSpace'] + modifyPack.bandwidth = data['bandwidth'] + modifyPack.guaranteedRam = data['guaranteedRam'] + modifyPack.cpuCores = data['cpuCores'] + modifyPack.save() + + data_ret = {'saveStatus': 1,'error_message': "None"} + json_data = json.dumps(data_ret) + return HttpResponse(json_data) + + except BaseException,msg: + data_ret = {'saveStatus': 0, 'error_message': str(msg)} + json_data = json.dumps(data_ret) + return HttpResponse(json_data) + + except KeyError,msg: + data_ret = {'saveStatus': 0, 'error_message': str(msg)} + json_data = json.dumps(data_ret) + return HttpResponse(json_data) \ No newline at end of file diff --git a/plogical/.my.cnf.4370 b/plogical/.my.cnf.4370 old mode 100644 new mode 100755 diff --git a/plogical/.mysql.4370 b/plogical/.mysql.4370 old mode 100644 new mode 100755 diff --git a/plogical/CyberCPLogFileWriter.py b/plogical/CyberCPLogFileWriter.py old mode 100644 new mode 100755 diff --git a/plogical/__init__.py b/plogical/__init__.py old mode 100644 new mode 100755 diff --git a/plogical/acl.py b/plogical/acl.py old mode 100644 new mode 100755 diff --git a/plogical/aclVMM.py b/plogical/aclVMM.py new file mode 100755 index 000000000..42a10ff4e --- /dev/null +++ b/plogical/aclVMM.py @@ -0,0 +1,277 @@ +#!/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() +from loginSystem.models import Administrator +from django.shortcuts import HttpResponse +from hypervisor.models import HyberVisors +from vpsManagement.models import SSHKeys, VPS +import json +from packages.models import VMPackage as Package + +class vmmACLManager: + + @staticmethod + def inspectHyperVisor(): + return 1 + + @staticmethod + def loadError(): + try: + return HttpResponse('You are not authorized to access this resource.') + except: + pass + + @staticmethod + def currentContextPermission(currentACL, context): + return 1 + + @staticmethod + def findServersObjs(currentACL, userID): + if currentACL['admin'] == 1: + return HyberVisors.objects.all() + else: + + hvList = [] + admin = Administrator.objects.get(pk=userID) + + hvs = admin.hybervisors_set.all() + + for items in hvs: + hvList.append(items) + + admins = Administrator.objects.filter(owner=admin.pk) + + for items in admins: + hvs = items.hybervisors_set.all() + for hv in hvs: + hvList.append(hv) + + return hvList + + @staticmethod + def prepareServers(serverObjs): + preparedServers = [] + for items in serverObjs: + data = {} + data['id'] = items.id + data['hypervisorOwner'] = items.hypervisorOwner.userName + data['hypervisorName'] = items.hypervisorName + data['hypervisorIP'] = items.hypervisorIP + data['vms'] = items.vps_set.all().count() + data['hypervisorStoragePath'] = items.hypervisorStoragePath + preparedServers.append(data) + return preparedServers + + @staticmethod + def fetchSSHkeys(currentACL, userID): + if currentACL['admin'] == 1: + + allKeys = SSHKeys.objects.all() + + json_data = "[" + checker = 0 + + for items in allKeys: + dic = { + 'keyName': items.keyName, + 'key': items.key, + } + + 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 + else: + + admin = Administrator.objects.get(pk=userID) + + sshkeys = admin.sshkeys_set.all() + + json_data = "[" + checker = 0 + + for items in sshkeys: + dic = { + 'keyName': items.keyName, + 'key': items.key, + } + + if checker == 0: + json_data = json_data + json.dumps(dic) + checker = 1 + else: + json_data = json_data + ',' + json.dumps(dic) + + admins = Administrator.objects.filter(owner=admin.pk) + + for items in admins: + + sshkeys = items.sshkeys_set.all() + for items in sshkeys: + dic = { + 'keyName': items.keyName, + 'key': items.key, + } + + 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 + + @staticmethod + def fetchSSHkeysObjects(currentACL, userID): + + if currentACL['admin'] == 1: + return SSHKeys.objects.all() + else: + + keysObjects = [] + admin = Administrator.objects.get(pk=userID) + sshkeys = admin.sshkeys_set.all() + + for items in sshkeys: + keysObjects.append(items) + + admins = Administrator.objects.filter(owner=admin.pk) + + for items in admins: + sshkeys = items.sshkeys_set.all() + for items in sshkeys: + keysObjects.append(items) + + + return keysObjects + + @staticmethod + def findSSHkeyNames(currentACL, userID): + sshKeysObjects = vmmACLManager.fetchSSHkeysObjects(currentACL, userID) + keyNames = [] + for items in sshKeysObjects: + keyNames.append(items.keyName) + return keyNames + + @staticmethod + def fetchHyperVisorObjects(currentACL, userID): + + if currentACL['admin'] == 1: + return HyberVisors.objects.all() + else: + hvObjects = [] + admin = Administrator.objects.get(pk=userID) + hvs = admin.hybervisors_set.all() + + for items in hvs: + hvObjects.append(items) + + admins = Administrator.objects.filter(owner=admin.pk) + + for items in admins: + hvs = items.hybervisors_set.all() + for items in hvs: + hvObjects.append(items) + + return hvObjects + + @staticmethod + def findHyperVisorNames(currentACL, userID): + hvs = vmmACLManager.fetchHyperVisorObjects(currentACL, userID) + hvNames = [] + for items in hvs: + hvNames.append(items.hypervisorName) + return hvNames + + @staticmethod + def findAllIPObjs(hv): + ipObjs = [] + allPools = hv.ippool_set.all() + for ipPool in allPools: + allIPs = ipPool.ipaddresses_set.all() + for ip in allIPs: + ipObjs.append(ip) + return ipObjs + + @staticmethod + def findAllIPs(hv): + allIps = vmmACLManager.findAllIPObjs(hv) + ipAddresses = [] + + for items in allIps: + if items.used == 1: + continue + ipAddresses.append(items.ipAddr) + return ipAddresses + + @staticmethod + def jsonIPs(hv): + allIPs = vmmACLManager.findAllIPs(hv) + + json_data = "[" + checker = 0 + + for items in allIPs: + dic = {'ipAddr': items} + + 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 + + @staticmethod + def findAllPackages(currentACL, userID): + if currentACL['admin'] == 1: + packageNames = [] + + packages = Package.objects.all() + for package in packages: + packageNames.append(package.packageName) + return packageNames + + @staticmethod + def checkOwner(currentACL, userID): + return 1 + + @staticmethod + def findAllVPSOBjs(currentACL, userID): + if currentACL['admin'] == 1: + return VPS.objects.all() + else: + vmObjects = [] + admin = Administrator.objects.get(pk=userID) + hvs = admin.vps_set.all() + + for items in hvs: + vmObjects.append(items) + + admins = Administrator.objects.filter(owner=admin.pk) + + for items in admins: + hvs = items.vps_set.all() + for items in hvs: + vmObjects.append(items) + + return vmObjects + + + + + diff --git a/plogical/adminPass.py b/plogical/adminPass.py old mode 100644 new mode 100755 diff --git a/plogical/alias.py b/plogical/alias.py old mode 100644 new mode 100755 diff --git a/plogical/applicationInstaller.py b/plogical/applicationInstaller.py old mode 100644 new mode 100755 diff --git a/plogical/backupManager.py b/plogical/backupManager.py old mode 100644 new mode 100755 index 005b38d45..7992baec5 --- a/plogical/backupManager.py +++ b/plogical/backupManager.py @@ -293,6 +293,7 @@ class BackupManager: execPath = "sudo python " + virtualHostUtilities.cyberPanel + "/plogical/backupUtilities.py" execPath = execPath + " submitRestore --backupFile " + backupFile + " --dir " + dir subprocess.Popen(shlex.split(execPath)) + time.sleep(4) final_dic = {'restoreStatus': 1, 'error_message': "None"} @@ -1181,9 +1182,11 @@ class BackupManager: def remoteBackupRestore(self, userID = None, data = None): try: currentACL = ACLManager.loadedACL(userID) + if ACLManager.currentContextPermission(currentACL, 'remoteBackups') == 0: return ACLManager.loadErrorJson('remoteTransferStatus', 0) + backupDir = data['backupDir'] backupDirComplete = "/home/backup/transfer-" + str(backupDir) diff --git a/plogical/backupSchedule.py b/plogical/backupSchedule.py old mode 100644 new mode 100755 diff --git a/plogical/backupScheduleLocal.py b/plogical/backupScheduleLocal.py old mode 100644 new mode 100755 diff --git a/plogical/backupUtilities.py b/plogical/backupUtilities.py old mode 100644 new mode 100755 diff --git a/plogical/childDomain.py b/plogical/childDomain.py old mode 100644 new mode 100755 diff --git a/plogical/dnsUtilities.py b/plogical/dnsUtilities.py old mode 100644 new mode 100755 diff --git a/plogical/domain.xml b/plogical/domain.xml old mode 100644 new mode 100755 diff --git a/plogical/filemanager.py b/plogical/filemanager.py old mode 100644 new mode 100755 diff --git a/plogical/findBWUsage.py b/plogical/findBWUsage.py old mode 100644 new mode 100755 diff --git a/plogical/firewallManager.py b/plogical/firewallManager.py old mode 100644 new mode 100755 diff --git a/plogical/firewallUtilities.py b/plogical/firewallUtilities.py old mode 100644 new mode 100755 diff --git a/plogical/ftpUtilities.py b/plogical/ftpUtilities.py old mode 100644 new mode 100755 diff --git a/plogical/getSystemInformation.py b/plogical/getSystemInformation.py old mode 100644 new mode 100755 diff --git a/plogical/hashPassword.py b/plogical/hashPassword.py old mode 100644 new mode 100755 diff --git a/plogical/installUtilities.py b/plogical/installUtilities.py old mode 100644 new mode 100755 diff --git a/plogical/letsEncrypt.py b/plogical/letsEncrypt.py old mode 100644 new mode 100755 diff --git a/plogical/mailUtilities.py b/plogical/mailUtilities.py old mode 100644 new mode 100755 diff --git a/plogical/modSec.py b/plogical/modSec.py old mode 100644 new mode 100755 diff --git a/plogical/mysqlUtilities.py b/plogical/mysqlUtilities.py old mode 100644 new mode 100755 index 7a3021f1a..232966f4c --- a/plogical/mysqlUtilities.py +++ b/plogical/mysqlUtilities.py @@ -138,7 +138,6 @@ class mysqlUtilities: cmd = shlex.split(command) - with open(tempStoragePath + "/" + databaseName + '.sql', 'r') as f: res = subprocess.call(cmd, stdin=f) diff --git a/plogical/phpUtilities.py b/plogical/phpUtilities.py old mode 100644 new mode 100755 diff --git a/plogical/processUtilities.py b/plogical/processUtilities.py old mode 100644 new mode 100755 diff --git a/plogical/randomPassword.py b/plogical/randomPassword.py old mode 100644 new mode 100755 diff --git a/plogical/remoteBackup.py b/plogical/remoteBackup.py old mode 100644 new mode 100755 diff --git a/plogical/remoteTransferUtilities.py b/plogical/remoteTransferUtilities.py old mode 100644 new mode 100755 diff --git a/plogical/serverLogs.py b/plogical/serverLogs.py old mode 100644 new mode 100755 diff --git a/plogical/sslUtilities.py b/plogical/sslUtilities.py old mode 100644 new mode 100755 diff --git a/plogical/test.py b/plogical/test.py old mode 100644 new mode 100755 diff --git a/plogical/tuning.py b/plogical/tuning.py old mode 100644 new mode 100755 diff --git a/plogical/upgrade.py b/plogical/upgrade.py old mode 100644 new mode 100755 diff --git a/plogical/vhost.py b/plogical/vhost.py old mode 100644 new mode 100755 diff --git a/plogical/virtualHostUtilities.py b/plogical/virtualHostUtilities.py old mode 100644 new mode 100755 index cd48b583a..7ff12ccaf --- a/plogical/virtualHostUtilities.py +++ b/plogical/virtualHostUtilities.py @@ -453,6 +453,27 @@ class virtualHostUtilities: cmd = shlex.split(command) subprocess.call(cmd) + command = 'hostname ' + virtualHost + cmd = shlex.split(command) + subprocess.call(cmd) + + hostNamePath = '/etc/cyberpanel/hostname' + + hostname = open(hostNamePath, 'w') + hostname.write(virtualHost) + hostname.close() + + f = open(pathToStoreSSLPrivKey) + key = f.read() + f = open(pathToStoreSSLFullChain) + cert = f.read() + + f= open('/usr/local/lscp/cyberpanel/noVNC/utils/self.pem', 'w') + f.write(key) + f.write(cert) + f.close() + + print "1,None" return 1,'None' diff --git a/plogical/website.py b/plogical/website.py old mode 100644 new mode 100755 index 198ce662e..9f0391a88 --- a/plogical/website.py +++ b/plogical/website.py @@ -161,14 +161,14 @@ class WebsiteManager: ## Create Configurations - execPath = "sudo python " + virtualHostUtilities.cyberPanel + "/plogical/virtualHostUtilities.py" + execPath = "sudo " + virtualHostUtilities.cyberPanel + "/plogical/virtualHostUtilities.py" execPath = execPath + " createVirtualHost --virtualHostName " + domain + \ " --administratorEmail " + adminEmail + " --phpVersion '" + phpSelection + \ "' --virtualHostUser " + externalApp + " --ssl " + str(data['ssl']) + " --dkimCheck " \ + str(data['dkimCheck']) + " --openBasedir " + str(data['openBasedir']) + \ ' --websiteOwner ' + websiteOwner + ' --package ' + packageName + ' --tempStatusPath ' + tempStatusPath - + logging.CyberCPLogFileWriter.writeToFile(execPath) subprocess.Popen(shlex.split(execPath)) time.sleep(2) diff --git a/requirments.txt b/requirments.txt index cacd75630..7becee280 100644 --- a/requirments.txt +++ b/requirments.txt @@ -52,3 +52,4 @@ urllib3==1.22 zope.component==4.4.1 zope.event==4.3.0 zope.interface==4.5.0 +libvirt-python==4.6.0 \ No newline at end of file diff --git a/static/backup/backup.js b/static/backup/backup.js index b83f9bcce..159550915 100644 --- a/static/backup/backup.js +++ b/static/backup/backup.js @@ -1550,4 +1550,480 @@ app.controller('remoteBackupControl', function($scope, $http, $timeout) { }); -///** Backup site ends **/// \ No newline at end of file +///** Backup site ends **/// + + +/////////////// Snapshots + +/* Java script code for Snapshots */ +app.controller('snapshotsCTRL', function($scope,$http) { + + $scope.getCurrentSnapshots = function(){ + + $scope.tronLoading = false; + + var url = "/backup/fetchCurrentSnapshots"; + + var data = { + hostName: $("#hostname").text() + }; + + var config = { + headers : { + 'X-CSRFToken': getCookie('csrftoken') + } + }; + + $http.post(url, data,config).then(ListInitialDatas, cantLoadInitialDatas); + + + function ListInitialDatas(response) { + + $scope.tronLoading = true; + $scope.snapshotTable = false; + + if(response.data.success === 1){ + + $scope.snapshots = JSON.parse(response.data.data); + } + else + { + new PNotify({ + title: 'Operation Failed!', + 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.getCurrentSnapshots(); + + /// Administrative Tasks + + $scope.tronLoading = true; + $scope.createSnapshotBox = true; + + + $scope.showSnapshotForm = function () { + $scope.createSnapshotBox = false; + $scope.createSnapshotBTN = true; + $scope.snapshotTable = true; + + }; + + + $scope.createSnapShot = function(){ + + $scope.tronLoading = false; + + + var url = "/backup/submitSnapshotCreation"; + + var data = { + hostName: $("#hostname").text(), + snapshotName: $scope.snapshotName + }; + + var config = { + headers : { + 'X-CSRFToken': getCookie('csrftoken') + } + }; + + $http.post(url, data,config).then(ListInitialDatas, cantLoadInitialDatas); + + + function ListInitialDatas(response) { + + $scope.tronLoading = true; + + if(response.data.success === 1){ + + new PNotify({ + title: 'Operation Successfull!', + text: response.data.successMessage, + type:'success' + }); + + $scope.getCurrentSnapshots(); + $scope.createSnapshotBox = true; + $scope.createSnapshotBTN = false; + + } + else + { + + new PNotify({ + title: 'Operation failed!', + text: response.data.error_message, + type:'error' + }); + } + } + function cantLoadInitialDatas(response) { + + $scope.tronLoading = true; + new PNotify({ + title: 'Operation failed!', + text: "Could not connect to server. Please refresh this page.", + type:'error' + }); + + + } + + }; + $scope.deleteSnapshot = function(snapshotName){ + + $scope.tronLoading = false; + + + var url = "/backup/deletSnapshot"; + + var data = { + hostName: $("#hostname").text(), + snapshotName: snapshotName + }; + + var config = { + headers : { + 'X-CSRFToken': getCookie('csrftoken') + } + }; + + $http.post(url, data,config).then(ListInitialDatas, cantLoadInitialDatas); + + + function ListInitialDatas(response) { + + $scope.tronLoading = true; + + if(response.data.success === 1){ + + new PNotify({ + title: 'Operation Successfull!', + text: response.data.successMessage, + type:'success' + }); + + $scope.getCurrentSnapshots(); + + } + else + { + + new PNotify({ + title: 'Operation failed!', + text: response.data.error_message, + type:'error' + }); + } + } + function cantLoadInitialDatas(response) { + + $scope.tronLoading = true; + new PNotify({ + title: 'Operation failed!', + text: "Could not connect to server. Please refresh this page.", + type:'error' + }); + + + } + + }; + $scope.revertToSnapshot = function(snapshotName){ + + $scope.tronLoading = false; + + + var url = "/backup/revertToSnapshot"; + + var data = { + hostName: $("#hostname").text(), + snapshotName: snapshotName + }; + + var config = { + headers : { + 'X-CSRFToken': getCookie('csrftoken') + } + }; + + $http.post(url, data,config).then(ListInitialDatas, cantLoadInitialDatas); + + + function ListInitialDatas(response) { + + $scope.tronLoading = true; + + if(response.data.success === 1){ + + new PNotify({ + title: 'Operation Successfull!', + text: response.data.successMessage, + type:'success' + }); + + } + else + { + + new PNotify({ + title: 'Operation failed!', + text: response.data.error_message, + type:'error' + }); + } + } + function cantLoadInitialDatas(response) { + + $scope.tronLoading = true; + new PNotify({ + title: 'Operation failed!', + text: "Could not connect to server. Please refresh this page.", + type:'error' + }); + + + } + + }; + + + $scope.changeRootPassword = function(vpsID){ + + $scope.tronLoading = false; + + + var url = "/vps/changeRootPassword"; + + var data = { + hostName: $("#vpsHostname").text(), + newPassword: $scope.newPassword + }; + + var config = { + headers : { + 'X-CSRFToken': getCookie('csrftoken') + } + }; + + $http.post(url, data,config).then(ListInitialDatas, cantLoadInitialDatas); + + + function ListInitialDatas(response) { + + $scope.tronLoading = true; + + if(response.data.success === 1){ + + $scope.successMessage = response.data.successMessage; + + new PNotify({ + title: 'Operation Successfull!', + text: response.data.successMessage, + type:'success' + }); + + } + else + { + new PNotify({ + title: 'Operation failed!', + text: response.data.error_message, + type:'error' + }); + } + } + function cantLoadInitialDatas(response) { + + $scope.tronLoading = true; + new PNotify({ + title: 'Operation failed!', + text: "Could not connect to server. Please refresh this page.", + type:'error' + }); + + + } + + }; + $scope.reinstallOS = function(vpsID){ + + $scope.tronLoading = false; + + + var url = "/vps/reInstallOS"; + + var data = { + hostName: $("#vpsHostname").text(), + rootPassword: $scope.reinstallPassword + }; + + var config = { + headers : { + 'X-CSRFToken': getCookie('csrftoken') + } + }; + + $http.post(url, data,config).then(ListInitialDatas, cantLoadInitialDatas); + + + function ListInitialDatas(response) { + + $scope.tronLoading = true; + + if(response.data.success === 1){ + + $scope.successMessage = response.data.successMessage; + + new PNotify({ + title: 'Operation Successfull!', + text: response.data.successMessage, + type:'success' + }); + + } + else + { + + new PNotify({ + title: 'Operation failed!', + text: response.data.error_message, + type:'error' + }); + } + } + function cantLoadInitialDatas(response) { + + $scope.tronLoading = true; + new PNotify({ + title: 'Operation failed!', + text: "Could not connect to server. Please refresh this page.", + type:'error' + }); + + + } + + }; + + + $scope.restartVPS = function(vpsID){ + + $scope.tronLoading = false; + $scope.poolCreationFailed = true; + $scope.poolCreated = true; + $scope.couldNotConnect = true; + + + + var url = "/vps/restartVPS"; + + var data = {vpsID: vpsID}; + + var config = { + headers : { + 'X-CSRFToken': getCookie('csrftoken') + } + }; + + $http.post(url, data,config).then(ListInitialDatas, cantLoadInitialDatas); + + + function ListInitialDatas(response) { + + if(response.data.success === 1){ + + $scope.tronLoading = true; + $scope.poolCreationFailed = true; + $scope.poolCreated = false; + $scope.couldNotConnect = true; + $scope.successMessage = response.data.successMessage; + $scope.getFurtherVPS(currentPageNumber); + } + else + { + $scope.tronLoading = true; + $scope.poolCreationFailed = false; + $scope.poolCreated = true; + $scope.couldNotConnect = true; + $scope.errorMessage = response.data.error_message; + + } + } + function cantLoadInitialDatas(response) { + $scope.tronLoading = true; + $scope.poolCreationFailed = true; + $scope.poolCreated = true; + $scope.couldNotConnect = false; + + } + + }; + $scope.shutdownVPS = function(vpsID){ + + $scope.tronLoading = false; + $scope.poolCreationFailed = true; + $scope.poolCreated = true; + $scope.couldNotConnect = true; + + + + var url = "/vps/shutdownVPS"; + + var data = {vpsID: vpsID}; + + var config = { + headers : { + 'X-CSRFToken': getCookie('csrftoken') + } + }; + + $http.post(url, data,config).then(ListInitialDatas, cantLoadInitialDatas); + + + function ListInitialDatas(response) { + + if(response.data.success === 1){ + + $scope.tronLoading = true; + $scope.poolCreationFailed = true; + $scope.poolCreated = false; + $scope.couldNotConnect = true; + $scope.successMessage = response.data.successMessage; + $scope.getFurtherVPS(currentPageNumber); + } + else + { + $scope.tronLoading = true; + $scope.poolCreationFailed = false; + $scope.poolCreated = true; + $scope.couldNotConnect = true; + $scope.errorMessage = response.data.error_message; + + } + } + function cantLoadInitialDatas(response) { + $scope.tronLoading = true; + $scope.poolCreationFailed = true; + $scope.poolCreated = true; + $scope.couldNotConnect = false; + + } + + }; + +}); +/* Java script code for Snapshots ends here */ \ No newline at end of file diff --git a/static/hypervisor/hypervisor.js b/static/hypervisor/hypervisor.js new file mode 100644 index 000000000..0e6bc6075 --- /dev/null +++ b/static/hypervisor/hypervisor.js @@ -0,0 +1,287 @@ +/** + * Created by usman on 9/5/17. + */ + + + +/* Java script code for HV */ + +app.controller('addHyperVisorCTRL', function($scope,$http) { + + $scope.tronLoading = true; + + $scope.submitCreateHyperVisor = function(){ + + $scope.rulesLoading = false; + + url = "/hv/submitCreateHyperVisor"; + + var data = { + name : $scope.name, + serverOwner : $scope.serverOwner, + serverIP : $scope.serverIP, + userName : $scope.userName, + password : $scope.password, + storagePath : $scope.storagePath + }; + + var config = { + headers : { + 'X-CSRFToken': getCookie('csrftoken') + } + }; + + + $http.post(url, data,config).then(ListInitialDatas, cantLoadInitialDatas); + + + function ListInitialDatas(response) { + + $scope.tronLoading = true; + + + if(response.data.status === 1){ + + new PNotify({ + title: 'Success!', + text: 'Server successfully added.', + type:'success' + }); + + } + else{ + + new PNotify({ + title: 'Error!', + text: response.data.errorMessage, + type:'error' + }); + + } + + } + function cantLoadInitialDatas(response) { + $scope.tronLoading = true; + new PNotify({ + title: 'Error!', + text: 'Could not connect to server, please refresh this page.', + type:'error' + }); + } + + }; + + + + + +}); + +/* Java script code for HV */ + +/* Java script code for List HVs */ + +app.controller('listHVCTRL', function($scope,$http) { + + $scope.tronLoading = true; + $scope.hvTable = false; + $scope.hvForm = true; + + $scope.submitCreateHyperVisor = function(){ + + $scope.tronLoading = false; + + url = "/hv/submitCreateHyperVisor"; + + var data = { + name : $scope.name, + serverOwner : $scope.serverOwner, + serverIP : $scope.serverIP, + userName : $scope.userName, + password : $scope.password, + storagePath : $scope.storagePath + }; + + var config = { + headers : { + 'X-CSRFToken': getCookie('csrftoken') + } + }; + + + $http.post(url, data,config).then(ListInitialDatas, cantLoadInitialDatas); + + + function ListInitialDatas(response) { + + $scope.tronLoading = true; + + + if(response.data.status === 1){ + + new PNotify({ + title: 'Success!', + text: 'Server successfully added.', + type:'success' + }); + + } + else{ + + new PNotify({ + title: 'Error!', + text: response.data.errorMessage, + type:'error' + }); + + } + + } + function cantLoadInitialDatas(response) { + $scope.tronLoading = true; + new PNotify({ + title: 'Error!', + text: 'Could not connect to server, please refresh this page.', + type:'error' + }); + } + + }; + $scope.manageServer = function (hypervisorName) { + $scope.hvTable = true; + $scope.hvForm = false; + $scope.name = hypervisorName; + }; + $scope.submitHyperVisorChanges = function(){ + + $scope.tronLoading = false; + + url = "/hv/submitHyperVisorChanges"; + + var data = { + name : $scope.name, + serverOwner : $scope.serverOwner, + userName : $scope.userName, + password : $scope.password, + storagePath : $scope.storagePath + }; + + var config = { + headers : { + 'X-CSRFToken': getCookie('csrftoken') + } + }; + + + $http.post(url, data,config).then(ListInitialDatas, cantLoadInitialDatas); + + + function ListInitialDatas(response) { + + $scope.tronLoading = true; + + + if(response.data.status === 1){ + + new PNotify({ + title: 'Success!', + text: 'Changes successfully saved.', + type:'success' + }); + + } + else{ + + new PNotify({ + title: 'Error!', + text: response.data.errorMessage, + type:'error' + }); + + } + + } + function cantLoadInitialDatas(response) { + $scope.tronLoading = true; + new PNotify({ + title: 'Error!', + text: 'Could not connect to server, please refresh this page.', + type:'error' + }); + } + + }; + $scope.hidehvForm = function (hypervisorIP) { + $scope.hvTable = false; + $scope.hvForm = true; + }; + $scope.setValues = function (hypervisorIP, action) { + $scope.hypervisorIP = hypervisorIP; + $scope.action = action; + }; + + $scope.controlCommands = function(){ + + $scope.tronLoading = false; + + url = "/hv/controlCommands"; + + var data = { + hypervisorIP : $scope.hypervisorIP, + action : $scope.action + }; + + var config = { + headers : { + 'X-CSRFToken': getCookie('csrftoken') + } + }; + + + $http.post(url, data,config).then(ListInitialDatas, cantLoadInitialDatas); + + + function ListInitialDatas(response) { + + $scope.tronLoading = true; + + + if(response.data.status === 1){ + + new PNotify({ + title: 'Success!', + text: 'Changes successfully saved.', + type:'success' + }); + + } + else{ + + new PNotify({ + title: 'Error!', + text: response.data.errorMessage, + type:'error' + }); + + } + + } + function cantLoadInitialDatas(response) { + $scope.tronLoading = true; + new PNotify({ + title: 'Error!', + text: 'Could not connect to server, please refresh this page.', + type:'error' + }); + } + + }; + + + + + +}); + +/* Java script code for List HVs */ + diff --git a/static/ipManagement/ipManagement.js b/static/ipManagement/ipManagement.js new file mode 100644 index 000000000..4f1c3c0b1 --- /dev/null +++ b/static/ipManagement/ipManagement.js @@ -0,0 +1,458 @@ +/** + * Created by usman on 5/18/18. + */ + + +/* Java script code to create IP Pool */ +app.controller('createIPPoolCTRL', function($scope,$http) { + + $scope.tronLoading = true; + $scope.poolCreationFailed = true; + $scope.poolCreated = true; + $scope.couldNotConnect = true; + + + $scope.createIPPool = function(){ + + $scope.tronLoading = false; + $scope.poolCreationFailed = true; + $scope.poolCreated = true; + $scope.couldNotConnect = true; + + + + var url = "/ip/submitIPPoolCreation"; + + var data = { + poolName: $scope.poolName, + poolGateway: $scope.poolGateway, + poolNetmask: $scope.poolNetmask, + poolStartingIP: $scope.poolStartingIP, + poolEndingIP: $scope.poolEndingIP, + hvName: $scope.hvName + }; + + var config = { + headers : { + 'X-CSRFToken': getCookie('csrftoken') + } + }; + + $http.post(url, data,config).then(ListInitialDatas, cantLoadInitialDatas); + + + function ListInitialDatas(response) { + + if(response.data.success === 1){ + + $scope.tronLoading = true; + $scope.poolCreationFailed = true; + $scope.poolCreated = false; + $scope.couldNotConnect = true; + + $scope.successMessage = response.data.successMessage; + } + else + { + $scope.tronLoading = true; + $scope.poolCreationFailed = false; + $scope.poolCreated = true; + $scope.couldNotConnect = true; + $scope.errorMessage = response.data.error_message; + + } + } + function cantLoadInitialDatas(response) { + $scope.tronLoading = true; + $scope.poolCreationFailed = true; + $scope.poolCreated = true; + $scope.couldNotConnect = false; + + } + + }; + +}); +/* Java script code to create IP Pool ends here */ + + +/* Java script code to List IP Pools */ +app.controller('listIPPoolsCTRL', function($scope,$http) { + + $scope.tronLoading = true; + $scope.poolCreationFailed = true; + $scope.poolCreated = true; + $scope.couldNotConnect = true; + + // Special + + $scope.currentRecords = true; + $scope.macBox = true; + + + $scope.fetchRecords = function(){ + + $scope.tronLoading = false; + $scope.poolCreationFailed = true; + $scope.poolCreated = true; + $scope.couldNotConnect = true; + + + + var url = "/ip/fetchIPsInPool"; + + var data = { + poolName: $scope.poolName + }; + + var config = { + headers : { + 'X-CSRFToken': getCookie('csrftoken') + } + }; + + $http.post(url, data,config).then(ListInitialDatas, cantLoadInitialDatas); + + + function ListInitialDatas(response) { + + if(response.data.success === 1){ + + $scope.tronLoading = true; + $scope.poolCreationFailed = true; + $scope.poolCreated = false; + $scope.couldNotConnect = true; + + // + + $scope.currentRecords = false; + + $scope.successMessage = response.data.successMessage; + $scope.records = JSON.parse(response.data.data); + } + else + { + $scope.tronLoading = true; + $scope.poolCreationFailed = false; + $scope.poolCreated = true; + $scope.couldNotConnect = true; + $scope.errorMessage = response.data.error_message; + + } + } + function cantLoadInitialDatas(response) { + $scope.tronLoading = true; + $scope.poolCreationFailed = true; + $scope.poolCreated = true; + $scope.couldNotConnect = false; + + } + + }; + + $scope.changeMac = function(ipAddr){ + + // Special + + $scope.macIP = ipAddr; + $scope.macBox = false; + }; + + $scope.changeMacFinal = function(){ + + $scope.tronLoading = false; + $scope.poolCreationFailed = true; + $scope.poolCreated = true; + $scope.couldNotConnect = true; + + + + var url = "/ip/submitNewMac"; + + var data = { + macIP: $scope.macIP, + newMac: $scope.newMac + }; + + var config = { + headers : { + 'X-CSRFToken': getCookie('csrftoken') + } + }; + + $http.post(url, data,config).then(ListInitialDatas, cantLoadInitialDatas); + + + function ListInitialDatas(response) { + + if(response.data.success === 1){ + + $scope.tronLoading = true; + $scope.poolCreationFailed = true; + $scope.poolCreated = false; + $scope.couldNotConnect = true; + + // + + $scope.currentRecords = false; + + $scope.successMessage = response.data.successMessage; + $scope.fetchRecords(); + $scope.macBox = true; + } + else + { + $scope.tronLoading = true; + $scope.poolCreationFailed = false; + $scope.poolCreated = true; + $scope.couldNotConnect = true; + $scope.errorMessage = response.data.error_message; + + } + } + function cantLoadInitialDatas(response) { + $scope.tronLoading = true; + $scope.poolCreationFailed = true; + $scope.poolCreated = true; + $scope.couldNotConnect = false; + + } + + }; + + $scope.deleteIP = function(id){ + + $scope.tronLoading = false; + $scope.poolCreationFailed = true; + $scope.poolCreated = true; + $scope.couldNotConnect = true; + + + + var url = "/ip/deleteIP"; + + var data = { + id: id + }; + + var config = { + headers : { + 'X-CSRFToken': getCookie('csrftoken') + } + }; + + $http.post(url, data,config).then(ListInitialDatas, cantLoadInitialDatas); + + + function ListInitialDatas(response) { + + if(response.data.success === 1){ + + $scope.tronLoading = true; + $scope.poolCreationFailed = true; + $scope.poolCreated = false; + $scope.couldNotConnect = true; + + // + + $scope.currentRecords = false; + $scope.successMessage = response.data.successMessage; + $scope.fetchRecords(); + + } + else + { + $scope.tronLoading = true; + $scope.poolCreationFailed = false; + $scope.poolCreated = true; + $scope.couldNotConnect = true; + $scope.errorMessage = response.data.error_message; + + } + } + function cantLoadInitialDatas(response) { + $scope.tronLoading = true; + $scope.poolCreationFailed = true; + $scope.poolCreated = true; + $scope.couldNotConnect = false; + + } + + }; + + $scope.deletePool = function(){ + + $scope.tronLoading = false; + + var url = "/ip/deletePool"; + + var data = { + poolName: $scope.poolName + }; + + var config = { + headers : { + 'X-CSRFToken': getCookie('csrftoken') + } + }; + + $http.post(url, data,config).then(ListInitialDatas, cantLoadInitialDatas); + + + function ListInitialDatas(response) { + + if(response.data.success === 1){ + + $scope.tronLoading = true; + + // + + new PNotify({ + title: 'Success!', + text: 'Pool successfully deleted.', + type:'success' + }); + } + else + { + $scope.tronLoading = true; + new PNotify({ + title: 'Operation Failed!', + text: response.data.error_message, + type:'error' + }); + } + } + function cantLoadInitialDatas(response) { + $scope.tronLoading = true; + new PNotify({ + title: 'Operation Failed!', + text: 'Could not connect to server, please refresh this page.', + type:'error' + }); + + + } + + }; + + $scope.addSingleIP = function(){ + + $scope.tronLoading = false; + + var url = "/ip/addSingleIP"; + + var data = { + poolName: $scope.poolName, + newIP: $scope.newIP + }; + + var config = { + headers : { + 'X-CSRFToken': getCookie('csrftoken') + } + }; + + $http.post(url, data,config).then(ListInitialDatas, cantLoadInitialDatas); + + + function ListInitialDatas(response) { + + if(response.data.success === 1){ + + $scope.tronLoading = true; + + // + + new PNotify({ + title: 'Success!', + text: 'IP successfully added.', + type:'success' + }); + $scope.fetchRecords(); + } + else + { + $scope.tronLoading = true; + new PNotify({ + title: 'Operation Failed!', + text: response.data.error_message, + type:'error' + }); + } + } + function cantLoadInitialDatas(response) { + $scope.tronLoading = true; + new PNotify({ + title: 'Operation Failed!', + text: 'Could not connect to server, please refresh this page.', + type:'error' + }); + + + } + + }; + + $scope.addMultipleIP = function(){ + + $scope.tronLoading = false; + + var url = "/ip/addMultipleIP"; + + var data = { + poolName: $scope.poolName, + startingIP: $scope.startingIP, + endingIP: $scope.endingIP + }; + + var config = { + headers : { + 'X-CSRFToken': getCookie('csrftoken') + } + }; + + $http.post(url, data,config).then(ListInitialDatas, cantLoadInitialDatas); + + + function ListInitialDatas(response) { + + if(response.data.success === 1){ + + $scope.tronLoading = true; + + // + + new PNotify({ + title: 'Success!', + text: 'IP successfully added.', + type:'success' + }); + $scope.fetchRecords(); + } + else + { + $scope.tronLoading = true; + new PNotify({ + title: 'Operation Failed!', + text: response.data.error_message, + type:'error' + }); + } + } + function cantLoadInitialDatas(response) { + $scope.tronLoading = true; + new PNotify({ + title: 'Operation Failed!', + text: 'Could not connect to server, please refresh this page.', + type:'error' + }); + + + } + + }; + + +}); +/* Java script code to List IP Pools ends here */ \ No newline at end of file diff --git a/static/packages/packages.js b/static/packages/packages.js index 925f00e40..6e65e392d 100644 --- a/static/packages/packages.js +++ b/static/packages/packages.js @@ -4,12 +4,6 @@ -/** - * Created by usman on 7/25/17. - */ - - - /* Utilities */ function getCookie(name) { @@ -31,15 +25,11 @@ function getCookie(name) { /* Utilities ends here */ - - /* Java script code to create Pacakge */ $("#packageCreationFailed").hide(); $("#packageCreated").hide(); - - app.controller('createPackage', function($scope,$http) { //$scope.pname = /([A-Z]){3,10}/gi; @@ -103,20 +93,15 @@ app.controller('createPackage', function($scope,$http) { }); - /* Java script code to to create Pacakge ends here */ - - /* Java script code to delete Pacakge */ - $("#deleteFailure").hide(); $("#deleteSuccess").hide(); $("#deletePackageButton").hide(); - app.controller('deletePackage', function($scope,$http) { @@ -179,12 +164,8 @@ app.controller('deletePackage', function($scope,$http) { }); - - /* Java script code to delete package ends here */ - - /* Java script code modify package */ $("#packageDetailsToBeModified").hide(); @@ -336,7 +317,294 @@ app.controller('modifyPackages', function($scope,$http) { }; }); - - - /* Java script code to Modify Pacakge ends here */ + +/**** VMM */ + + + +/* Java script code to create Pacakge */ + +app.controller('createPackageVMM', function($scope,$http) { + + $scope.tronLoading = true; + $scope.poolCreationFailed = true; + $scope.poolCreated = true; + $scope.couldNotConnect = true; + + + $scope.insertPackInDB = function(){ + + $scope.tronLoading = false; + $scope.poolCreationFailed = true; + $scope.poolCreated = true; + $scope.couldNotConnect = true; + + + + var url = "/packages/submitPackageVMM"; + + var data = { + packageName: $scope.packageName, + diskSpace: $scope.diskSpace, + guaranteedRam: $scope.guaranteedRam, + bandwidth: $scope.bandwidth, + cpuCores: $scope.cpuCores, + }; + + var config = { + headers : { + 'X-CSRFToken': getCookie('csrftoken') + } + }; + + $http.post(url, data,config).then(ListInitialDatas, cantLoadInitialDatas); + + + function ListInitialDatas(response) { + + if(response.data.success === 1){ + + $scope.tronLoading = true; + $scope.poolCreationFailed = true; + $scope.poolCreated = false; + $scope.couldNotConnect = true; + + $scope.successMessage = response.data.successMessage; + } + else + { + $scope.tronLoading = true; + $scope.poolCreationFailed = false; + $scope.poolCreated = true; + $scope.couldNotConnect = true; + $scope.errorMessage = response.data.error_message; + + } + } + function cantLoadInitialDatas(response) { + $scope.tronLoading = true; + $scope.poolCreationFailed = true; + $scope.poolCreated = true; + $scope.couldNotConnect = false; + + } + + }; + +}); + +/* Java script code to to create Pacakge ends here */ + + + +/* Java script code to delete Pacakge */ + + +$("#deleteFailure").hide(); +$("#deleteSuccess").hide(); + +$("#deletePackageButton").hide(); + + +app.controller('deletePackageVMM', function($scope,$http) { + + + $scope.deletePackage = function(){ + + $("#deletePackageButton").fadeIn(); + + + }; + + $scope.deletePackageFinal = function(){ + + + var packageName = $scope.packageToBeDeleted; + + + + url = "/packages/submitDeleteVMM"; + + var data = { + packageName: packageName + }; + + var config = { + headers : { + 'X-CSRFToken': getCookie('csrftoken') + } + }; + + $http.post(url, data,config).then(ListInitialDatas, cantLoadInitialDatas); + + + function ListInitialDatas(response) { + + if (response.data.deleteStatus === 0) + { + $scope.errorMessage = response.data.error_message; + $("#deleteFailure").fadeIn(); + $("#deleteSuccess").hide(); + $("#deletePackageButton").hide(); + + } + else{ + $("#deleteFailure").hide(); + $("#deleteSuccess").fadeIn(); + $("#deletePackageButton").hide(); + $scope.deletedPackage = packageName; + + } + + + } + function cantLoadInitialDatas(response) { + console.log("not good"); + } + + + }; + +}); + + + +/* Java script code to delete package ends here */ + +$("#packageDetailsToBeModified").hide(); +$("#modifyFailure").hide(); +$("#modifySuccess").hide(); +$("#modifyButton").hide(); +$("#packageLoading").hide(); +$("#successfullyModified").hide(); + +app.controller('modifyPackagesVMM', function($scope,$http) { + + $scope.fetchDetails = function(){ + + $("#packageLoading").show(); + $("#successfullyModified").hide(); + + var packageName = $scope.packageToBeModified; + console.log(packageName); + + + url = "/packages/submitModifyVMM"; + + var data = { + packageName: packageName + }; + + var config = { + headers : { + 'X-CSRFToken': getCookie('csrftoken') + } + }; + + $http.post(url, data,config).then(ListInitialDatas, cantLoadInitialDatas); + + + function ListInitialDatas(response) { + + if (response.data.modifyStatus === 0) + { + $scope.errorMessage = response.data.error_message; + $("#modifyFailure").fadeIn(); + $("#modifySuccess").hide(); + $("#modifyButton").hide(); + $("#packageLoading").hide(); + + + } + else{ + $("#modifyButton").show(); + $scope.packageName = response.data.packageName; + $scope.diskSpace = response.data.diskSpace; + $scope.guaranteedRam = response.data.guaranteedRam; + $scope.bandwidth = response.data.bandwidth; + $scope.cpuCores = response.data.cpuCores; + + $scope.modifyButton = "Save Details"; + + $("#packageDetailsToBeModified").fadeIn(); + + $("#modifyFailure").hide(); + $("#modifySuccess").fadeIn(); + $("#packageLoading").hide(); + } + + + } + function cantLoadInitialDatas(response) { + console.log("not good"); + } + + }; + + + + $scope.modifyPackageFunc = function () { + + + $("#modifyFailure").hide(); + $("#modifySuccess").hide(); + $("#packageLoading").show(); + $("#packageDetailsToBeModified").hide(); + + + url = "/packages/saveChangesVMM"; + + var data = { + packageName: $scope.packageToBeModified, + diskSpace:$scope.diskSpace, + bandwidth:$scope.bandwidth, + guaranteedRam:$scope.guaranteedRam, + cpuCores:$scope.cpuCores + }; + + var config = { + headers : { + 'X-CSRFToken': getCookie('csrftoken') + } + }; + + $http.post(url, data,config).then(ListInitialDatas, cantLoadInitialDatas); + + + function ListInitialDatas(response) { + + if (response.data.saveStatus == 0) + { + $scope.errorMessage = response.data.error_message; + $("#modifyFailure").fadeIn(); + $("#modifySuccess").hide(); + $("#modifyButton").hide(); + $("#packageLoading").hide(); + + + } + else{ + $("#modifyButton").hide(); + + $("#successfullyModified").fadeIn(); + $("#modifyFailure").hide(); + $("#packageLoading").hide(); + $scope.packageModified = packageName; + + + + + } + + + } + function cantLoadInitialDatas(response) { + console.log("not good"); + } + + + + }; + +}); diff --git a/static/userManagment/userManagment.js b/static/userManagment/userManagment.js index 4c82b4068..af1bffaad 100644 --- a/static/userManagment/userManagment.js +++ b/static/userManagment/userManagment.js @@ -58,7 +58,7 @@ app.controller('createUserCtr', function($scope,$http) { function ListInitialDatas(response) { - if(response.data.createStatus == 1){ + if(response.data.createStatus === 1){ $scope.userCreated = false; $scope.userCreationFailed = true; diff --git a/static/vpsManagement/backup.png b/static/vpsManagement/backup.png new file mode 100644 index 0000000000000000000000000000000000000000..486f5edb86dc22a5380833a098008cc3580dcf58 GIT binary patch literal 2414 zcmV-!36b`RP)s#p|6p~_36gyJKhRRV~BBA^7wOG0?0NEk**NJ1XF zdw>07HyJYbCIf6_?=*gA?(FXOeCPbm{qDWzoO|x?08$8OH$7GgpdtpzsQ~~C!=O9h zNbOQPJo4%ZyKh+dx982^ zy}Y>=KJSg0w){J9&Ln@)Yzv>iXtpgM54i2f-4&$-PCMPg@2M=u=S#HFm)P=^J4V}gc2|_3rqVlO z09j*iBsHyvMYE@(lyEpqdQ_8U^QSt-fQI@y=Dze44fS;xE*AhhzS+pG@?!3O_(@Vy z(`Y=}z}%OnQFo*UmmwI2P+YW$%AFFCA zd7p;*I)-Kr=O3@k=Y?4d$h>?cjYsQQ{qZsYJ}>-`x+67=8*w&e?_{xaNj5iU_oVS? zgGDpCcTZMLp2*tUZ)E&{44Rr6Dg0=uC9Y$xfW4LFhzK`N&f$v7h9ZDz-o@sP>)BUX z9@Tscz*Bb*B4bcb5QC@hQSw)PXVLs+_)sqCmyX-z;xUvJ6?@nhEjt#DF~BekRFzOL zNGKFW1VX_es)|G>XNE*RTY@HPnutWdD;7<2I84|y5fOr66H^s2#1hvr2K4Dah(iaz zW8uGM5e|nD5%Lzij;hk9-{3aQf&F`Vbmk78dqDBH4IY2B1k*jesZSd@_Atadv=upaBko87@2iFUY{R;gaj{t_|sI@6&A32 zXDOzd^v)Q_sO)k0{E1dgMHyx|OnOFtMrDt~pO|ck+o1v0y9ES6#9DH~ybafCLiTkx zb<`vva)M*7odnk&hvqn7F+dfDTy!bPDQT#-FB^QpF#P@`3xEEFm*VsJE&Py+F2&_? zTlE)Yw#AA!1kjYgY20@2)Ofe$lw#5B>D1L8cFsg7UJxQHBe-17=nvf<582~yBR%6h z017{Ri(TbK(N=aH!r?HW2(Spq?%L{O!cpM&s=5Y1L|z6aVc##uij|^H=!xQpnEL<` z$rq6(o1;-g=66LSqjAm+b*}atH7_if8!b;bh;R1p+;K^fkI z;W9ke|MfbuAINGO2S(mGf=SbUh0EhIfLS8)qKKT-xj4=M5%B_xfvMgkuipCNtz3M= z#TMQ9SD(-AuS}N2fM0=!fMp_*bfWPbX8`aDa4SHlB_#QO%V+7-e_KQa&n)NdNAhTH zY-ybzj0aA5)Nx`TZ~&+U2nWN2gW=S&HD#7bQ2E+&n(CTp)kg8(6Ak7#15`B^$Zh>C zBGo`g<9@TMrgczuTyWwoa7yu$0r74?yz!F(@oqr8al!_O$P5vwX*~dMC-O6o)kbG` zj>5@Y0lk0#5HLJOAR);^uVFo{qRd`+5`1d35As zBjji2onaAO@#o8_E~;kT^BdF*nF72G+#g$WyB;Te1*mERFcFy1T-PkCo?NYa*X^_D zc70mOn(1o^HU zfS*UHUBGp!THXb9R|97y^=SX3d$i^#YHG8p`eF*8s$Fsrd0@#S@+^Nw7uGu;Xat&U zj{I2b@Ak{$PJA(PDzVb~YV5~&|KdP|Lm?nK3bei*{wY_u8^YFr_wwela(TXm|KQy> z__W|%3tx~wzeE0`Ws5ERN6Qx5^6`MJ0Xx3gNZIzy7QUot6UAGKvr?!jhm`?DsPv7V8 z4~O{0g%>k(&H`SZvw(|+W>Q=81FJuN4}f)r1$=*~no$>?&X;pXvE|LtTyxo(wwg=M zIg_O~jpgItOki~HUeQc+2j>d6?jgA6{zu5n9EymL;PvvyJ8xlkMM*o&^A8ST=&*D| z3|^Sx;**W5ESkqh4r9#VzPMd3{BAc_E!^LxITnsFz>MbgdJ;UiTrLFgcoGm1)HEX+ zjeI6}j7V;<7?JOSMdNk3a2WWyiuX zSHP9OoIrW;*L=BtEt|ev4@5G#{E5k2b+qx*(iayr!{C8sj}*LTLOX@#u;efkX|C2*RBKR06_{v_*UqEElU z`22ngpV5CXF1IyApZS_<$Ws7&O6(Y;#>F$F1BeiH` g&d{B=&r9L|0HTHb{eLJBp8x;=07*qoM6N<$g11zY_y7O^ literal 0 HcmV?d00001 diff --git a/static/vpsManagement/changePassword.png b/static/vpsManagement/changePassword.png new file mode 100644 index 0000000000000000000000000000000000000000..fc13efa5281ae55a6040be0e92de00dd80e31947 GIT binary patch literal 2919 zcmV-t3z+nYP)JPJ#cY-I=2^=lsvinKLuHLQ2Uf_U}JhZMyV_5Mm{Q zRwOg|Hb8I^$!?_Fp&IUIo0}UVcGoBYdyaHmCnPTdv(J^C(}Zp*xcB14jc>vT0VB@; z=UiJhosfd-FJ9dErr5Xd>uS?&9N^m@`LXC$b=NY*bm)}gAih+Hj?e96uKqY7V_|EpO?0s6iZqWl4^Znhr^3vsA>eS- z#nbz%i0Y@Keo4K;uU4wG)F~7Ts07+V7SHT3+1YE^?E$yN!_5OM2^dbB>O28o4!Zd5 z?rIDxOGY0}hMy7pJt>ESB zU7S~$@46+SeL(W+mnN@%Y0^F*u?oz?^C~ksnrbsTBD%se2Leu-jCN*`iD6sF%i*XC z0G9$!uW_LkptpTM^5};K`}%S{zAz|wa*d0HRk?(zBf4&RMaQr*`DI(k%Vl**N9=ZF z2AC2yeN}FMf3Q_!QFVUg51o?S@`|44JixxbOy8kX`F)G31rN5Kj@72G$}t_vT#gX1 zKjNk*o>`mCLBYn0^4F7pXJ{Go<#!RrW{RPMGct0iX7H z?ax1L(NGIyyta_Vk?@(rb|frm3*|GQij3|;V@?K+5U``q17xMYWyce%HT7me5*nK$g*jv(OFPlLS;1$9J>#=vvJ72^mwDg;_Xh0U%a2ryW=Yb{RzqQd(yn! zY4Ju!W(ElXcP)%LU~vYHUWq+_xRTA?nM$SHEf~@rNKy)vxdhQvM%T4-68z-+!Aa{K zg`+n@8yCmyi%Tb*2S{7k&RZgWdmpqKbAO3 z0A#MPpIQ-SX_fAn&ZSj4Ppt?Oa8JJQ8H*`<7)e`#m)gsD>xBQTudh@A*UpJ^_rf8^ zBR`5MeHsHe5!cw%QO@=fFECaGQ{34mjf+g&kCIRT^SPpWM1_prUsLubsza5}eK zF4H6nDhyTyQ>>~@P1#e}SWFuMW1(9j=XrcupT)D_*tX+Eo9Z;;bQnYImBT$6#@JoCg1yPmJRdpj(1ZP6aqL z=y%G-DTM^Wx<**n_#)a7`9rYHdi2mKsN zIP>^$E^#d3;ovwyEK0zq;mRp7=v-htUkVZsH8hfDewU>u81CGOnHtJzPxW__IB^iN z(xWsDhP!r=9uDWo8qr?jN86BA))pu&;>Y%44D{s4ria4}cYTIT=bkGP-Jg@{@62g4 zQ$q}Q?!?mbucnixLewan?h3YsQiU((Pi_A@@uO|1-U?=}`x&l4J<)^jGSK!q0Cj8c z!#Af1fPuYlF!=fV2+c#?5AMfX*GT;9J@kF@5=e{c)|;uk;3@!O?OO@&_$LU3+RN{x zZ2k(8p$6I4!TQ{Lcx``e6uN`^Cov#;QpzU?cWQ=&%F3e;sSJy;+D%e^C)yr?e zJ);50kdWj{33s+JA*_t@bNZ0FrG8mMl)xfGX5BS3NcnR)dCX#VP)_KGEI z2{f(GX%mV@aLq=Wuu=HuT}aK!+aRZ!6x6J|4gb6gb7b8!8VIi0h){ATYM^O76-(CU zv}yioW?ub3&TN^GPbEnMu_GUojz@CZ;$6EiqP=;t@uPdt!^d;l51xqf-$w$*OxM^iazf(x0lR;=b4SjapMBF~Svet<6WQUeUC4B%ZuiYz%IupS z%gG7xuHCk5;`o7_H9zZyM{;t)aMx!AZ7=4NdjEqz|NYoTOA0=Z<*y~h?Zb=@P}O`b zl}pwlR2O9pEtttcG+%(qrgipCp?E7u$NH#PbUD=*--r+@{_|Rp=@g2mj6l+#);`ZaMYee%`A=4=; zmtKvlBA93Uis~WCwfy6E!3&YJ6#TVwR>2=HeiNYx*tnnvP2@XNa0zHa(pZ+5a>J$z zjb({~&cirKaCL1Iuj>3Y^mN0kTCA>(7VR%efKRo!rY`c0Cc!)6gKr!k#GWtOd&m2O zWWrSVs6Rl*u=7xv@aPi{CH>Kcuz8f>4d-Q+9koE6z_-_7v{(rO&d;l6~ ROpgEn002ovPDHLkV1kcKro;dM literal 0 HcmV?d00001 diff --git a/static/vpsManagement/close-32.png b/static/vpsManagement/close-32.png new file mode 100644 index 0000000000000000000000000000000000000000..c18fdd957143537c15670894e147749f58245521 GIT binary patch literal 1039 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabRA=0VB8$w6XFWw{{R2~-@ktl^6As3 z-@bi&_wL<$F!%rlA3uKl^y$;*&!4}1`2rLMiUCF704N0na4v)aR09#mBoQj#ef$VC z>FtLPZ{C9t(BwC7fZUHj8{WMKqW2*5?$f(>A78)u`1;+4w{JhZ1(NSRy?yr)q!L7a zdixfr{?q&SpFkuCfw><(zzlhJ=l;8U58pj_{QmC44?vIIxeqiGXxG~-H{V{n_4eBB zw>R#*z54*H=Fz){Pu@R!{{H#P4?y(d)rXg_K&}Eh=KcFyN-npQU2m&-+}7~Ct?6}J z+xxbz?`?hm+Xnu330z4M;+&3`^&!Sjg=pHE)=e9Dp+)0e%NvHZoX6))zj zdbxVr%k{fnt=|4>?T(MnUVM7>1{lh~@SOeV9XBxAl1qa8f*IJ@IXJmw{Ku-@gqn<=la(Wre4UV~EA+ zHlG8F9~vIqy?NiRT?=pLH_et(pJlQ-$*Ckb(MUwZ^f-%`vGVE9v(&bws3|wD*`|`5 z*Rp3pvP-6slt%ZKhwZP+dCqwsWB9qyEWkM8?4jbx8yo(3D0f(k2zyW7*wj_0x#7Q1 z)PXxCKB8|MWgJ+gE+%|W|6;oIfJ)G-RR>DS=4f4Do#!iXa2uzAs6!fW%hgAxjwskI zG>{Bsopk9D=OG@gdj-vkLLQ$^YTA9``8D^XhSr3qlP6biky!I;a$v}U6YA!(j4eXd z7q4)b=)Z2G`ho@5rX5_xIA7HF8Bf*SA2K(Wo?IZ)aDMi_BAz7St^)RulPrpCV&Bs^ zmh)MzkXBq1mafLe_VtF2!SYpXf{|qK(jaGjPsLq7Fv`;_-Sziw}yxU|^n z7q8`n&0^g?0Wsc&Ix=2SkN>L9yilaReAa80`SXs=y0uL2KBu16n}|>5n>(7ewKnf< fowi3{QXa#~RrU|=iE2FoCJ_ctS3j3^P6HRku@w4GpweSjx+XxV6B98{mb4rwDvv_3({6@c(8`}?viV^? zSDG)%PRUm!oJ^)D6beRKR(f7iLQXOx`($dPEo3+8z8;Q=x&QuubUK|%HO6E{9OXwW zt*tHFY?6JlpY*f|k)UW_(~(FF!|O1IC6*39yI>IweYUImbcxAWlCCPCGpeFz^fckd;J+oR$C7X3&A9_{%Jm$Y|7${d z3$H!nnxAzsjq_r|r)sL)P)id|m>V)Xc4Qj*%L}iS(VxpLc|$Y$GFdlzh0(ljdj+*gaM9lNqzVoS{Q7`jk$@GIItVtOlY zUjSwf-)>6N#uw0=T-U~GLaDz@FF$12H8xX5+GvU8KIdDGN1XP0e50$@3w~G+t-p27 zoIJZ~H+`fwzYm-Z^kB~9eA)aecU zYS!-ru^a1uxZ%B*`w=Tv4ZkX#^GWx0pc!p%xAgzhEX-CKy!}~4*Ca!Op$qm^x~_d^ SS}l*rKSP1JfTL#1l>Y%KT=z!+ literal 0 HcmV?d00001 diff --git a/static/vpsManagement/delete.png b/static/vpsManagement/delete.png new file mode 100644 index 0000000000000000000000000000000000000000..9d29e3bd683dab85712d02483c08400201b1f8e6 GIT binary patch literal 894 zcmV-^1A+XBP)1t2YZ(!59TRLB5pp6GbR-vW9~5^b7IY&PcqbT^CK{P38<`~;pD-SsDjcOWA)+!L zr!^p`DI2XY9;hiBuQVdAFd(rrA-6gt&N3p@JSWyYDAzkD-$*UlJ}BWwE#5aJ-#RDW zI3?*wEa5yS>`5-`M=b40F5)*O=|C&#LM-V*D(XZl@=Y-1IwOd;-NH6tI zG3Yud={qRtJ1OctDeFEe>^~~(Kq~A;GVMSs?M^)ILM!e=Ebdc4?p8zYSVrzxNAE){ z?^Z@po zWKr`-FY`(-^IApoTt@R;NAq1q^Ik~vWKi>EQS)X|^JY@>XH)b`FZ5eO^jt>tUr6*| zNc3k>^k`G{OfdCRIrUpY^;|>sUrF_0N%dw?^=MS}YE<@3F!oI`_GV7^Pci$|(EHZW z{MXU^*V6ph)BM@f{MpnmaSu=c002jHQchC<9UdPaAR!_nBUoEoTwGpWa&&cfcX)Vs zdU|_%rlzQ6PYQo2}biZU8M~qvHp0)MKE^9sSZ6&IY9PGeJH`avqXog2*_+Fi+o%>iLmj2K4~Y zK-2V9{DVebe{X4;t_4W5$3)lh_n72Gc#Dbb7*s?h$MO59=tj7UN=l%ek{$Aw6m=q; zQ?gd*i6963#gT9tK{{bFsMzEG&Vq_@nD8k!Iey=#7=tbk66UtU+^z@dfHqPVVz)># z#O;u>W+-z>{Or0*Wh0a4as5)()Y782wEk})u^(Psjcu4ZNqnW{%lvf(Zf5XkOaw(_6s-alh2_$~ zl%QnYYH2LCger}8vxy&EZPT=7HOA7!4}~U1bVG|;ytJu?7^qedcK{J$EGrdQYzqU$ z3n*0J?1$-`a{d;p2h)-+`m9O8LNeAp|NR1S*v(A9x)=t??x+Itc$6lR?EF0|MGxZ&LqF z8@IadTBQX-h&NPNy8TIjc`?)3u;))qd~%$-Tz#nMxzW$w&81vA`yZ<)NrmOPSfkeX zvg_1e6pgR{#-bP&J^g`YBQZEI#5YG9>HPlom^8*&=nVl1zj|);^S8tzYft#67qAc@ zEILTh_|EIM`Nz610Qj(cEq=O5PRs0}@{6nFZz+2SO&lF6mC~7a|X{v1lagBtgU(#mQj)Pw-&PU ztw@(T=Pn%i=wE#PkqH0~H~Zpt$R6;h;*swGUe=2jUU-4n*jP8Z;yRRhB zqxxqunMNH1rW@7%eQ88c?k+uJL9R(N|~WDrL6AtVI7UeBsktC%=(qC&oR?_K~IfV8wU-g)O8r+jcK0Ar1y zpdkAD`!So%G6?s>jvYGysI9FfFE4M*d~wSxpwsC%efl(0r%nYdJ>k3WzPoR^C!TnM z$jGr}tZthI!@|N8LAZDC-l+N)E?l6yyPLIZ*N&+lPCWvjZ(8+0M$Kk3v9YlP1qE^P zl6Q2R1Mm3<`&>h>3}zxVRXtR*OcXk@6iocCdKyVvI(kLO(1ljOyxYjvqfxc6PRu zFIlpLBS(&K>Cz>IUzwSicK!M4tFNf8u4eV>)sC8F7mwNCqm0J^aJK{QhD+I?6}7ds zq@|@16cj{YU?4`LkqZ|tD0FVzxWT-6^JHBf9v(dV?6d6Iv&Uvo9vmEG*REYW|NQf4 zG#UyD9&DNJGBzlL5QT+>!rR;1#*UYlmnbMGka~v>9dcOb?%lhk-rc)*#gZjU6#41t z=}r%VE@gvFO- z^78VybLS3ud3n73_S*n#+qO;aA!xN)va+%iZ1H|@DH|**Dx$Zy7qDz(q^G9?aPs6y zl9Q9^>+7Siu#gWv_&`x^n$P0r2zl!^6YUgu1#q0DOIYNlHpmlo>b9@%Iic4M0>> z6kr)Q)~{dB`Sa(gsi|Szx^;5*XW6o4quR*G$dH_3!h{JJ3-D4Bv^xvb*48>T3zU?U*o?9r9UUSxG*l!cB#5D*At@gk8WPKwFL!8b z>C&ZQU|>K9Aw*G8k(5VAM=SJFQ&XkQ%F0UN;o{tcf690s7hz1{9~H8R!I)Yw#T z=FAxZ2ybt1(b?Il$m{IvRBVn~lhJ4t?d|PS&tx(QKunl0LEOA~Q8GCppjN9{w{9Jw zp`id=zkZ#}%uI%ch7|7-y1ToHkB_IMq=eYmSXx?IWZus||Lo8wm$Jcw2M==lw&hdV z;cT$ExtS9uPLPq20ayY6mbHFUQxj^n8i4HVZ1VH-si>%+p`k&_t?2IVmNuP*O9w&g z_V!3NIBV7{a&vPD2nb+cV1R~(1_0KqS)*uVPEL-z9?2S4tXQFV0TUM&=af$_4S-gw z1#H>iaCmunF=fgW;C~FyisAPoS>r3OyuyJ42beQw4!d{nX6x3iPWklE0?^;zZ!`K@ znche?n3a`e^73-tefM2jTU$AF=n(I{_a5N*CFz1&woY=W@ zrwrKSuz2xe8yj_XbyQSTP*+z+P*4y{mo7!8(@7m)Utel!YA~D4Hsy6X zog65Km$8S(Z17Qrd<4qN%botP$co`x&Yhi|96fpzqtPg*yZ;ybrUR0fE?p8r2$7wg zEdcTI%P+gRgWn(9wr#WeKjZ;4{@TbzL_`oA91Otn<;&6ObR;As{91D^LsL_e^|BEx z$L7SONs~llW23wOoQICCt}da~YOOusAXpAg3P6O1hbwkw|7hsy>Jo{GiNhb^M4O|t zo}Qk>#KaI26C>Zc{2mYx5I|;TCgaDC2P~i678e&2A0ID2j_T>@p|G%!j*bpRSs?^X zO-+=RmJZJ=5JJ51e|30z%a$!oLWpu9MERyoo2~&OGBUDzq|AvV4^PWuQ85w} z(GWodl_)3?MbwBOK0fjxBKV=;kKl(15z&vR;ExEJM2VtNVoWq(G@H1(F}vAEc4ub$ zRo9Q%#MxxJy1S-l7ug)xkEL#(I(53Ly6RR9F*BwWeVekj9PJV;I;DptI9hQHM!(PU zSUTtScLEkh~S}X;yo1I zZ<3-s1B}k{PNe-o{GDF|hDd}p5d#Q57MI^b-anWGof56~0i@&@juh5|VKmG)#ekd% zEGfh%rJ?tMX=wZ@w75sHT4UMKJ<;C_r&2oo{}cm=2&tIumt#91$9G1ICO{NG zq6mm0NX&&?xC^i)*p`69fGZ0}xV-$&Y2=oui(;E7+AA(XikF!EaTQ;;Ii zyp%G;9Q_64m6S0-&@zC_`v8`KL2CGiaFROE`wTjN2A7clL?M*IKlmBolqXdXXmQ9~VHwrAAYhFk zN=HKLtOvaz;Ex0siXuX1EnTF8<&vY&q(FQFWCdV1ScoWU35f*7Cy}HB^2@O)V;jK! zs5+pD22jYFfSeF*br9PC3R}%7dPl>MA)5pv!bxCqDzAR8gOBLTR)jD(@qTJQWaxU)&*wGSH z7pHOr3b^z1lBJqGU^yUKf&o*$1`{>sA4r^uUAap~NDGiSzE#u0lU0CR$(= zZ&$~#53cM7kADluiRj!OgOAzOt{<}Yu@~J5Hp4exL1-u^Xw114lxh!+V{ZU*YzNr> z1Mo*tcmK-(99ezqf7w7Ke2*+M9k9FB#ur|L#tud(1*825`2DYjzhQR4l>?J6)R;_< z&jk;<)rLFK(&4A+L>8rsH-R;lzqM%iXoXT;5N(el-WFH_{wUZv0*rap6<(|pN<#Uf z$Khue#uHlyjh`(6plmmc`S)wj#PKQ>9TjB;(K`>fY!N^|=dGbqe>3gtqG!}!OUj}Evb#OXwYj~ztp-Bcz zf-D%twLoz#;0-~R_k!);tG&V>1$!f4!Qj+fNUI1=wZfZo5!}|5km>nNm3CTU(pO~S z!t48KCaX_&68t}6)*E0B9q&72kmw+T^mi1RkkZG*(C~Cu3ug8hJS?RgG7oy5nn{PVpHi>iYr z4gu;)jEXrqt~1ay1Bf}X-?k7T+26_3peY7CuxV2_16L-+$BZj)y7%Gkr1)x)xB>TW z-fWQ+Taj$K&4j^Qdp2&2aFZe)5;b7Mv(K(b50CExkj$yYR9uxGb-udsz72X80Rj-| zhm$Y8_Sy~1Mqu7x!m*b*j^E=+|3+pGxkfe>aqh&Uyo) w4FU4s0UJA#uH5y#b|MPDQ>Ou9c_>QUzohM4KG}dx2mk;807*qoM6N<$f>}&=LI3~& literal 0 HcmV?d00001 diff --git a/static/vpsManagement/pnotify.custom.min.css b/static/vpsManagement/pnotify.custom.min.css new file mode 100644 index 000000000..1c26861fd --- /dev/null +++ b/static/vpsManagement/pnotify.custom.min.css @@ -0,0 +1,10 @@ +/*! +Author : Hunter Perrin +Version : 3.2.0 +Link : http://sciactive.com/pnotify/ +*/.ui-pnotify{top:36px;right:36px;position:absolute;height:auto;z-index:2}body>.ui-pnotify{position:fixed;z-index:100040}.ui-pnotify-modal-overlay{background-color:rgba(0,0,0,.4);top:0;left:0;position:absolute;height:100%;width:100%;z-index:1}body>.ui-pnotify-modal-overlay{position:fixed;z-index:100039}.ui-pnotify.ui-pnotify-in{display:block!important}.ui-pnotify.ui-pnotify-move{transition:left .5s ease,top .5s ease,right .5s ease,bottom .5s ease}.ui-pnotify.ui-pnotify-fade-slow{transition:opacity .4s linear;opacity:0}.ui-pnotify.ui-pnotify-fade-slow.ui-pnotify.ui-pnotify-move{transition:opacity .4s linear,left .5s ease,top .5s ease,right .5s ease,bottom .5s ease}.ui-pnotify.ui-pnotify-fade-normal{transition:opacity .25s linear;opacity:0}.ui-pnotify.ui-pnotify-fade-normal.ui-pnotify.ui-pnotify-move{transition:opacity .25s linear,left .5s ease,top .5s ease,right .5s ease,bottom .5s ease}.ui-pnotify.ui-pnotify-fade-fast{transition:opacity .1s linear;opacity:0}.ui-pnotify.ui-pnotify-fade-fast.ui-pnotify.ui-pnotify-move{transition:opacity .1s linear,left .5s ease,top .5s ease,right .5s ease,bottom .5s ease}.ui-pnotify.ui-pnotify-fade-in{opacity:1}.ui-pnotify .ui-pnotify-shadow{-webkit-box-shadow:0 6px 28px 0 rgba(0,0,0,.1);-moz-box-shadow:0 6px 28px 0 rgba(0,0,0,.1);box-shadow:0 6px 28px 0 rgba(0,0,0,.1)}.ui-pnotify-container{background-position:0 0;padding:.8em;height:100%;margin:0}.ui-pnotify-container:after{content:" ";visibility:hidden;display:block;height:0;clear:both}.ui-pnotify-container.ui-pnotify-sharp{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.ui-pnotify-title{display:block;margin-bottom:.4em;margin-top:0}.ui-pnotify-text{display:block}.ui-pnotify-icon,.ui-pnotify-icon span{display:block;float:left;margin-right:.2em}.ui-pnotify.stack-bottomleft,.ui-pnotify.stack-topleft{left:25px;right:auto}.ui-pnotify.stack-bottomleft,.ui-pnotify.stack-bottomright{bottom:25px;top:auto}.ui-pnotify.stack-modal{left:50%;right:auto;margin-left:-150px} +.brighttheme{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.brighttheme.ui-pnotify-container{padding:18px}.brighttheme .ui-pnotify-title{margin-bottom:12px}.brighttheme-notice{background-color:#ffffa2;border:0 solid #ff0;color:#4f4f00}.brighttheme-info{background-color:#8fcedd;border:0 solid #0286a5;color:#012831}.brighttheme-success{background-color:#aff29a;border:0 solid #35db00;color:#104300}.brighttheme-error{background-color:#ffaba2;background-image:repeating-linear-gradient(135deg,transparent,transparent 35px,rgba(255,255,255,.3) 35px,rgba(255,255,255,.3) 70px);border:0 solid #ff1800;color:#4f0800}.brighttheme-icon-closer,.brighttheme-icon-info,.brighttheme-icon-notice,.brighttheme-icon-sticker,.brighttheme-icon-success{position:relative;width:16px;height:16px;font-size:12px;font-weight:700;line-height:16px;font-family:"Courier New",Courier,monospace;border-radius:50%}.brighttheme-icon-closer:after,.brighttheme-icon-info:after,.brighttheme-icon-notice:after,.brighttheme-icon-sticker:after,.brighttheme-icon-success:after{position:absolute;top:0;left:4px}.brighttheme-icon-notice{background-color:#2e2e00;color:#ffffa2;margin-top:2px}.brighttheme-icon-notice:after{content:"!"}.brighttheme-icon-info{background-color:#012831;color:#8fcedd;margin-top:2px}.brighttheme-icon-info:after{content:"i"}.brighttheme-icon-success{background-color:#104300;color:#aff29a;margin-top:2px}.brighttheme-icon-success:after{content:"\002713"}.brighttheme-icon-error{position:relative;width:0;height:0;border-left:8px solid transparent;border-right:8px solid transparent;border-bottom:16px solid #2e0400;font-size:0;line-height:0;color:#ffaba2;margin-top:1px}.brighttheme-icon-error:after{position:absolute;top:1px;left:-4px;font-size:12px;font-weight:700;line-height:16px;font-family:"Courier New",Courier,monospace;content:"!"}.brighttheme-icon-closer,.brighttheme-icon-sticker{display:inline-block}.brighttheme-icon-closer:after{top:-4px;content:"\002715"}.brighttheme-icon-sticker:after{top:-5px;content:"\01D1BC";-moz-transform:rotate(-90deg);-webkit-transform:rotate(-90deg);-o-transform:rotate(-90deg);-ms-transform:rotate(-90deg);transform:rotate(-90deg)}.brighttheme-icon-sticker.brighttheme-icon-stuck:after{-moz-transform:rotate(180deg);-webkit-transform:rotate(180deg);-o-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.brighttheme .ui-pnotify-action-bar{padding-top:12px}.brighttheme .ui-pnotify-action-bar input,.brighttheme .ui-pnotify-action-bar textarea{display:block;width:100%;margin-bottom:12px!important}.brighttheme .ui-pnotify-action-button{text-transform:uppercase;font-weight:700;padding:4px 8px;border:none;background:0 0}.brighttheme .ui-pnotify-action-button.btn-primary{border:none;border-radius:0}.brighttheme-notice .ui-pnotify-action-button.btn-primary{background-color:#ff0;color:#4f4f00}.brighttheme-info .ui-pnotify-action-button.btn-primary{background-color:#0286a5;color:#012831}.brighttheme-success .ui-pnotify-action-button.btn-primary{background-color:#35db00;color:#104300}.brighttheme-error .ui-pnotify-action-button.btn-primary{background-color:#ff1800;color:#4f0800} +.ui-pnotify-closer,.ui-pnotify-sticker{float:right;margin-left:.2em} +.ui-pnotify-history-container{position:absolute;top:0;right:18px;width:70px;border-top:none;padding:0;-webkit-border-top-left-radius:0;-moz-border-top-left-radius:0;border-top-left-radius:0;-webkit-border-top-right-radius:0;-moz-border-top-right-radius:0;border-top-right-radius:0;z-index:10000}.ui-pnotify-history-container.ui-pnotify-history-fixed{position:fixed}.ui-pnotify-history-container .ui-pnotify-history-header{padding:2px;text-align:center}.ui-pnotify-history-container button{cursor:pointer;display:block;width:100%}.ui-pnotify-history-container .ui-pnotify-history-pulldown{display:block;margin:0 auto}.ui-pnotify-history-brighttheme{background-color:#8fcedd;border:0 solid #0286a5;color:#012831}.ui-pnotify-history-brighttheme button{text-transform:uppercase;font-weight:700;padding:4px 8px;border:none;background:0 0}.ui-pnotify-history-brighttheme .ui-pnotify-history-pulldown::after{display:block;font-size:16px;line-height:14px;padding-bottom:4px;content:"⌄";text-align:center;font-weight:700;font-family:Arial,sans-serif} +.ui-pnotify-container{position:relative;left:0}@media (max-width:480px){.ui-pnotify-mobile-able.ui-pnotify{position:fixed;top:0;right:0;left:0;width:auto!important;font-size:1.2em;-webkit-font-smoothing:antialiased;-moz-font-smoothing:antialiased;-ms-font-smoothing:antialiased;font-smoothing:antialiased}.ui-pnotify-mobile-able.ui-pnotify .ui-pnotify-shadow{-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;border-bottom-width:5px}.ui-pnotify-mobile-able .ui-pnotify-container{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.ui-pnotify-mobile-able.ui-pnotify.stack-bottomleft,.ui-pnotify-mobile-able.ui-pnotify.stack-topleft{left:0;right:0}.ui-pnotify-mobile-able.ui-pnotify.stack-bottomleft,.ui-pnotify-mobile-able.ui-pnotify.stack-bottomright{left:0;right:0;bottom:0;top:auto}.ui-pnotify-mobile-able.ui-pnotify.stack-bottomleft .ui-pnotify-shadow,.ui-pnotify-mobile-able.ui-pnotify.stack-bottomright .ui-pnotify-shadow{border-top-width:5px;border-bottom-width:1px}} +.ui-pnotify.ui-pnotify-nonblock-fade{opacity:.2}.ui-pnotify.ui-pnotify-nonblock-hide{display:none!important} diff --git a/static/vpsManagement/pnotify.custom.min.js b/static/vpsManagement/pnotify.custom.min.js new file mode 100644 index 000000000..cac2934ec --- /dev/null +++ b/static/vpsManagement/pnotify.custom.min.js @@ -0,0 +1,31 @@ +/* +PNotify 3.2.0 sciactive.com/pnotify/ +(C) 2015 Hunter Perrin; Google, Inc. +license Apache-2.0 +*/ +!function(t,i){"function"==typeof define&&define.amd?define("pnotify",["jquery"],function(s){return i(s,t)}):"object"==typeof exports&&"undefined"!=typeof module?module.exports=i(require("jquery"),global||t):t.PNotify=i(t.jQuery,t)}("undefined"!=typeof window?window:this,function(t,i){var s=function(i){var e,o,n={dir1:"down",dir2:"left",push:"bottom",spacing1:36,spacing2:36,context:t("body"),modal:!1},a=t(i),r=function(){o=t("body"),c.prototype.options.stack.context=o,a=t(i),a.bind("resize",function(){e&&clearTimeout(e),e=setTimeout(function(){c.positionAll(!0)},10)})},h=function(i){var s=t("
",{class:"ui-pnotify-modal-overlay"});return s.prependTo(i.context),i.overlay_close&&s.click(function(){c.removeStack(i)}),s},c=function(t){this.state="initializing",this.timer=null,this.animTimer=null,this.styles=null,this.elem=null,this.container=null,this.title_container=null,this.text_container=null,this.animating=!1,this.timerHide=!1,this.parseOptions(t),this.init()};return t.extend(c.prototype,{version:"3.2.0",options:{title:!1,title_escape:!1,text:!1,text_escape:!1,styling:"brighttheme",addclass:"",cornerclass:"",auto_display:!0,width:"300px",min_height:"16px",type:"notice",icon:!0,animation:"fade",animate_speed:"normal",shadow:!0,hide:!0,delay:8e3,mouse_reset:!0,remove:!0,insert_brs:!0,destroy:!0,stack:n},modules:{},runModules:function(t,i){var s;for(var e in this.modules)s="object"==typeof i&&e in i?i[e]:i,"function"==typeof this.modules[e][t]&&(this.modules[e].notice=this,this.modules[e].options="object"==typeof this.options[e]?this.options[e]:{},this.modules[e][t](this,"object"==typeof this.options[e]?this.options[e]:{},s))},init:function(){var i=this;return this.modules={},t.extend(!0,this.modules,c.prototype.modules),"object"==typeof this.options.styling?this.styles=this.options.styling:this.styles=c.styling[this.options.styling],this.elem=t("
",{class:"ui-pnotify "+this.options.addclass,css:{display:"none"},"aria-live":"assertive","aria-role":"alertdialog",mouseenter:function(t){if(i.options.mouse_reset&&"out"===i.animating){if(!i.timerHide)return;i.cancelRemove()}i.options.hide&&i.options.mouse_reset&&i.cancelRemove()},mouseleave:function(t){i.options.hide&&i.options.mouse_reset&&"out"!==i.animating&&i.queueRemove(),c.positionAll()}}),"fade"===this.options.animation&&this.elem.addClass("ui-pnotify-fade-"+this.options.animate_speed),this.container=t("
",{class:this.styles.container+" ui-pnotify-container "+("error"===this.options.type?this.styles.error:"info"===this.options.type?this.styles.info:"success"===this.options.type?this.styles.success:this.styles.notice),role:"alert"}).appendTo(this.elem),""!==this.options.cornerclass&&this.container.removeClass("ui-corner-all").addClass(this.options.cornerclass),this.options.shadow&&this.container.addClass("ui-pnotify-shadow"),!1!==this.options.icon&&t("
",{class:"ui-pnotify-icon"}).append(t("",{class:!0===this.options.icon?"error"===this.options.type?this.styles.error_icon:"info"===this.options.type?this.styles.info_icon:"success"===this.options.type?this.styles.success_icon:this.styles.notice_icon:this.options.icon})).prependTo(this.container),this.title_container=t("

",{class:"ui-pnotify-title"}).appendTo(this.container),!1===this.options.title?this.title_container.hide():this.options.title_escape?this.title_container.text(this.options.title):this.title_container.html(this.options.title),this.text_container=t("
",{class:"ui-pnotify-text","aria-role":"alert"}).appendTo(this.container),!1===this.options.text?this.text_container.hide():this.options.text_escape?this.text_container.text(this.options.text):this.text_container.html(this.options.insert_brs?String(this.options.text).replace(/\n/g,"
"):this.options.text),"string"==typeof this.options.width&&this.elem.css("width",this.options.width),"string"==typeof this.options.min_height&&this.container.css("min-height",this.options.min_height),"top"===this.options.stack.push?c.notices=t.merge([this],c.notices):c.notices=t.merge(c.notices,[this]),"top"===this.options.stack.push&&this.queuePosition(!1,1),this.options.stack.animation=!1,this.runModules("init"),this.state="closed",this.options.auto_display&&this.open(),this},update:function(i){var s=this.options;return this.parseOptions(s,i),this.elem.removeClass("ui-pnotify-fade-slow ui-pnotify-fade-normal ui-pnotify-fade-fast"),"fade"===this.options.animation&&this.elem.addClass("ui-pnotify-fade-"+this.options.animate_speed),this.options.cornerclass!==s.cornerclass&&this.container.removeClass("ui-corner-all "+s.cornerclass).addClass(this.options.cornerclass),this.options.shadow!==s.shadow&&(this.options.shadow?this.container.addClass("ui-pnotify-shadow"):this.container.removeClass("ui-pnotify-shadow")),!1===this.options.addclass?this.elem.removeClass(s.addclass):this.options.addclass!==s.addclass&&this.elem.removeClass(s.addclass).addClass(this.options.addclass),!1===this.options.title?this.title_container.slideUp("fast"):this.options.title!==s.title&&(this.options.title_escape?this.title_container.text(this.options.title):this.title_container.html(this.options.title),!1===s.title&&this.title_container.slideDown(200)),!1===this.options.text?this.text_container.slideUp("fast"):this.options.text!==s.text&&(this.options.text_escape?this.text_container.text(this.options.text):this.text_container.html(this.options.insert_brs?String(this.options.text).replace(/\n/g,"
"):this.options.text),!1===s.text&&this.text_container.slideDown(200)),this.options.type!==s.type&&this.container.removeClass(this.styles.error+" "+this.styles.notice+" "+this.styles.success+" "+this.styles.info).addClass("error"===this.options.type?this.styles.error:"info"===this.options.type?this.styles.info:"success"===this.options.type?this.styles.success:this.styles.notice),(this.options.icon!==s.icon||!0===this.options.icon&&this.options.type!==s.type)&&(this.container.find("div.ui-pnotify-icon").remove(),!1!==this.options.icon&&t("
",{class:"ui-pnotify-icon"}).append(t("",{class:!0===this.options.icon?"error"===this.options.type?this.styles.error_icon:"info"===this.options.type?this.styles.info_icon:"success"===this.options.type?this.styles.success_icon:this.styles.notice_icon:this.options.icon})).prependTo(this.container)),this.options.width!==s.width&&this.elem.animate({width:this.options.width}),this.options.min_height!==s.min_height&&this.container.animate({minHeight:this.options.min_height}),this.options.hide?s.hide||this.queueRemove():this.cancelRemove(),this.queuePosition(!0),this.runModules("update",s),this},open:function(){this.state="opening",this.runModules("beforeOpen");var t=this;return this.elem.parent().length||this.elem.appendTo(this.options.stack.context?this.options.stack.context:o),"top"!==this.options.stack.push&&this.position(!0),this.animateIn(function(){t.queuePosition(!0),t.options.hide&&t.queueRemove(),t.state="open",t.runModules("afterOpen")}),this},remove:function(s){this.state="closing",this.timerHide=!!s,this.runModules("beforeClose");var e=this;return this.timer&&(i.clearTimeout(this.timer),this.timer=null),this.animateOut(function(){if(e.state="closed",e.runModules("afterClose"),e.queuePosition(!0),e.options.remove&&e.elem.detach(),e.runModules("beforeDestroy"),e.options.destroy&&null!==c.notices){var i=t.inArray(e,c.notices);-1!==i&&c.notices.splice(i,1)}e.runModules("afterDestroy")}),this},get:function(){return this.elem},parseOptions:function(i,s){this.options=t.extend(!0,{},c.prototype.options),this.options.stack=c.prototype.options.stack;for(var e,o=[i,s],n=0;n(i.context.is(o)?a.height():i.context.prop("scrollHeight"))||"up"===i.dir1&&i.nextpos1+s.height()>(i.context.is(o)?a.height():i.context.prop("scrollHeight"))||"left"===i.dir1&&i.nextpos1+s.width()>(i.context.is(o)?a.width():i.context.prop("scrollWidth"))||"right"===i.dir1&&i.nextpos1+s.width()>(i.context.is(o)?a.width():i.context.prop("scrollWidth")))&&(i.nextpos1=i.firstpos1,i.nextpos2+=i.addpos2+(void 0===i.spacing2?25:i.spacing2),i.addpos2=0),"number"==typeof i.nextpos2&&(i.animation?s.css(p,i.nextpos2+"px"):(s.removeClass("ui-pnotify-move"),s.css(p,i.nextpos2+"px"),s.css(p),s.addClass("ui-pnotify-move"))),i.dir2){case"down":case"up":s.outerHeight(!0)>i.addpos2&&(i.addpos2=s.height());break;case"left":case"right":s.outerWidth(!0)>i.addpos2&&(i.addpos2=s.width())}switch("number"==typeof i.nextpos1&&(i.animation?s.css(c,i.nextpos1+"px"):(s.removeClass("ui-pnotify-move"),s.css(c,i.nextpos1+"px"),s.css(c),s.addClass("ui-pnotify-move"))),i.dir1){case"down":case"up":i.nextpos1+=s.height()+(void 0===i.spacing1?25:i.spacing1);break;case"left":case"right":i.nextpos1+=s.width()+(void 0===i.spacing1?25:i.spacing1)}}return this}},queuePosition:function(t,i){return e&&clearTimeout(e),i||(i=10),e=setTimeout(function(){c.positionAll(t)},i),this},cancelRemove:function(){return this.timer&&i.clearTimeout(this.timer),this.animTimer&&i.clearTimeout(this.animTimer),"closing"===this.state&&(this.state="open",this.animating=!1,this.elem.addClass("ui-pnotify-in"),"fade"===this.options.animation&&this.elem.addClass("ui-pnotify-fade-in")),this},queueRemove:function(){var t=this;return this.cancelRemove(),this.timer=i.setTimeout(function(){t.remove(!0)},isNaN(this.options.delay)?0:this.options.delay),this}}),t.extend(c,{notices:[],reload:s,removeAll:function(){t.each(c.notices,function(t,i){i.remove&&i.remove(!1)})},removeStack:function(i){t.each(c.notices,function(t,s){s.remove&&s.options.stack===i&&s.remove(!1)})},positionAll:function(i){if(e&&clearTimeout(e),e=null,c.notices&&c.notices.length)t.each(c.notices,function(t,s){var e=s.options.stack;e&&(e.overlay&&e.overlay.hide(),e.nextpos1=e.firstpos1,e.nextpos2=e.firstpos2,e.addpos2=0,e.animation=i)}),t.each(c.notices,function(t,i){i.position()});else{var s=c.prototype.options.stack;s&&(delete s.nextpos1,delete s.nextpos2)}},styling:{brighttheme:{container:"brighttheme",notice:"brighttheme-notice",notice_icon:"brighttheme-icon-notice",info:"brighttheme-info",info_icon:"brighttheme-icon-info",success:"brighttheme-success",success_icon:"brighttheme-icon-success",error:"brighttheme-error",error_icon:"brighttheme-icon-error"},bootstrap3:{container:"alert",notice:"alert-warning",notice_icon:"glyphicon glyphicon-exclamation-sign",info:"alert-info",info_icon:"glyphicon glyphicon-info-sign",success:"alert-success",success_icon:"glyphicon glyphicon-ok-sign",error:"alert-danger",error_icon:"glyphicon glyphicon-warning-sign"}}}),c.styling.fontawesome=t.extend({},c.styling.bootstrap3),t.extend(c.styling.fontawesome,{notice_icon:"fa fa-exclamation-circle",info_icon:"fa fa-info",success_icon:"fa fa-check",error_icon:"fa fa-warning"}),i.document.body?r():t(r),c};return s(i)}); +//# sourceMappingURL=pnotify.js.map +// Animate +!function(n,i){"function"==typeof define&&define.amd?define("pnotify.animate",["jquery","pnotify"],i):"object"==typeof exports&&"undefined"!=typeof module?module.exports=i(require("jquery"),require("./pnotify")):i(n.jQuery,n.PNotify)}("undefined"!=typeof window?window:this,function(n,i){return i.prototype.options.animate={animate:!1,in_class:"",out_class:""},i.prototype.modules.animate={init:function(n,i){this.setUpAnimations(n,i),n.attention=function(i,t){n.elem.one("webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend",function(){n.elem.removeClass(i),t&&t.call(n)}).addClass("animated "+i)}},update:function(n,i,t){i.animate!=t.animate&&this.setUpAnimations(n,i)},setUpAnimations:function(n,i){if(i.animate){n.options.animation="none",n.elem.removeClass("ui-pnotify-fade-slow ui-pnotify-fade-normal ui-pnotify-fade-fast"),n._animateIn||(n._animateIn=n.animateIn),n._animateOut||(n._animateOut=n.animateOut),n.animateIn=this.animateIn.bind(this),n.animateOut=this.animateOut.bind(this);var t=400;"slow"===n.options.animate_speed?t=600:"fast"===n.options.animate_speed?t=200:n.options.animate_speed>0&&(t=n.options.animate_speed),t/=1e3,n.elem.addClass("animated").css({"-webkit-animation-duration":t+"s","-moz-animation-duration":t+"s","animation-duration":t+"s"})}else n._animateIn&&n._animateOut&&(n.animateIn=n._animateIn,delete n._animateIn,n.animateOut=n._animateOut,delete n._animateOut,n.elem.addClass("animated"))},animateIn:function(n){this.notice.animating="in";var i=this;n=function(){i.notice.elem.removeClass(i.options.in_class),this&&this.call(),i.notice.animating=!1}.bind(n),this.notice.elem.show().one("webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend",n).removeClass(this.options.out_class).addClass("ui-pnotify-in").addClass(this.options.in_class)},animateOut:function(n){this.notice.animating="out";var i=this;n=function(){i.notice.elem.removeClass("ui-pnotify-in "+i.options.out_class),this&&this.call(),i.notice.animating=!1}.bind(n),this.notice.elem.one("webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend",n).removeClass(this.options.in_class).addClass(this.options.out_class)}},i}); +//# sourceMappingURL=pnotify.animate.js.map +// Buttons +!function(o,s){"function"==typeof define&&define.amd?define("pnotify.buttons",["jquery","pnotify"],s):"object"==typeof exports&&"undefined"!=typeof module?module.exports=s(require("jquery"),require("./pnotify")):s(o.jQuery,o.PNotify)}("undefined"!=typeof window?window:this,function(o,s){return s.prototype.options.buttons={closer:!0,closer_hover:!0,sticker:!0,sticker_hover:!0,show_on_nonblock:!1,labels:{close:"Close",stick:"Stick",unstick:"Unstick"},classes:{closer:null,pin_up:null,pin_down:null}},s.prototype.modules.buttons={init:function(s,i){var n=this;s.elem.on({mouseenter:function(o){!n.options.sticker||s.options.nonblock&&s.options.nonblock.nonblock&&!n.options.show_on_nonblock||n.sticker.trigger("pnotify:buttons:toggleStick").css("visibility","visible"),!n.options.closer||s.options.nonblock&&s.options.nonblock.nonblock&&!n.options.show_on_nonblock||n.closer.css("visibility","visible")},mouseleave:function(o){n.options.sticker_hover&&n.sticker.css("visibility","hidden"),n.options.closer_hover&&n.closer.css("visibility","hidden")}}),this.sticker=o("
",{class:"ui-pnotify-sticker","aria-role":"button","aria-pressed":s.options.hide?"false":"true",tabindex:"0",title:s.options.hide?i.labels.stick:i.labels.unstick,css:{cursor:"pointer",visibility:i.sticker_hover?"hidden":"visible"},click:function(){s.options.hide=!s.options.hide,s.options.hide?s.queueRemove():s.cancelRemove(),o(this).trigger("pnotify:buttons:toggleStick")}}).bind("pnotify:buttons:toggleStick",function(){var i=null===n.options.classes.pin_up?s.styles.pin_up:n.options.classes.pin_up,e=null===n.options.classes.pin_down?s.styles.pin_down:n.options.classes.pin_down;o(this).attr("title",s.options.hide?n.options.labels.stick:n.options.labels.unstick).children().attr("class","").addClass(s.options.hide?i:e).attr("aria-pressed",s.options.hide?"false":"true")}).append("").trigger("pnotify:buttons:toggleStick").prependTo(s.container),(!i.sticker||s.options.nonblock&&s.options.nonblock.nonblock&&!i.show_on_nonblock)&&this.sticker.css("display","none"),this.closer=o("
",{class:"ui-pnotify-closer","aria-role":"button",tabindex:"0",title:i.labels.close,css:{cursor:"pointer",visibility:i.closer_hover?"hidden":"visible"},click:function(){s.remove(!1),n.sticker.css("visibility","hidden"),n.closer.css("visibility","hidden")}}).append(o("",{class:null===i.classes.closer?s.styles.closer:i.classes.closer})).prependTo(s.container),(!i.closer||s.options.nonblock&&s.options.nonblock.nonblock&&!i.show_on_nonblock)&&this.closer.css("display","none")},update:function(o,s){!s.closer||o.options.nonblock&&o.options.nonblock.nonblock&&!s.show_on_nonblock?this.closer.css("display","none"):s.closer&&this.closer.css("display","block"),!s.sticker||o.options.nonblock&&o.options.nonblock.nonblock&&!s.show_on_nonblock?this.sticker.css("display","none"):s.sticker&&this.sticker.css("display","block"),this.sticker.trigger("pnotify:buttons:toggleStick"),this.closer.find("span").attr("class","").addClass(null===s.classes.closer?o.styles.closer:s.classes.closer),s.sticker_hover?this.sticker.css("visibility","hidden"):o.options.nonblock&&o.options.nonblock.nonblock&&!s.show_on_nonblock||this.sticker.css("visibility","visible"),s.closer_hover?this.closer.css("visibility","hidden"):o.options.nonblock&&o.options.nonblock.nonblock&&!s.show_on_nonblock||this.closer.css("visibility","visible")}},o.extend(s.styling.brighttheme,{closer:"brighttheme-icon-closer",pin_up:"brighttheme-icon-sticker",pin_down:"brighttheme-icon-sticker brighttheme-icon-stuck"}),o.extend(s.styling.bootstrap3,{closer:"glyphicon glyphicon-remove",pin_up:"glyphicon glyphicon-pause",pin_down:"glyphicon glyphicon-play"}),o.extend(s.styling.fontawesome,{closer:"fa fa-times",pin_up:"fa fa-pause",pin_down:"fa fa-play"}),s}); +//# sourceMappingURL=pnotify.buttons.js.map +// Callbacks +!function(o,t){"function"==typeof define&&define.amd?define("pnotify.callbacks",["jquery","pnotify"],t):"object"==typeof exports&&"undefined"!=typeof module?module.exports=t(require("jquery"),require("./pnotify")):t(o.jQuery,o.PNotify)}("undefined"!=typeof window?window:this,function(o,t){var i=t.prototype.init,e=t.prototype.open,n=t.prototype.remove;return t.prototype.init=function(){this.options.before_init&&this.options.before_init(this.options),i.apply(this,arguments),this.options.after_init&&this.options.after_init(this)},t.prototype.open=function(){var o;this.options.before_open&&(o=this.options.before_open(this)),!1!==o&&(e.apply(this,arguments),this.options.after_open&&this.options.after_open(this))},t.prototype.remove=function(o){var t;this.options.before_close&&(t=this.options.before_close(this,o)),!1!==t&&(n.apply(this,arguments),this.options.after_close&&this.options.after_close(this,o))},t}); +//# sourceMappingURL=pnotify.callbacks.js.map +// Confirm +!function(t,n){"function"==typeof define&&define.amd?define("pnotify.confirm",["jquery","pnotify"],n):"object"==typeof exports&&"undefined"!=typeof module?module.exports=n(require("jquery"),require("./pnotify")):n(t.jQuery,t.PNotify)}("undefined"!=typeof window?window:this,function(t,n){return n.prototype.options.confirm={confirm:!1,prompt:!1,prompt_class:"",prompt_default:"",prompt_multi_line:!1,align:"right",buttons:[{text:"Ok",addClass:"",promptTrigger:!0,click:function(t,n){t.remove(),t.get().trigger("pnotify.confirm",[t,n])}},{text:"Cancel",addClass:"",click:function(t){t.remove(),t.get().trigger("pnotify.cancel",t)}}]},n.prototype.modules.confirm={init:function(n,o){this.container=t('
').css("text-align",o.align).appendTo(n.container),o.confirm||o.prompt?this.makeDialog(n,o):this.container.hide()},update:function(t,n){n.confirm?(this.makeDialog(t,n),this.container.show()):this.container.hide().empty()},afterOpen:function(t,n){n.prompt&&this.prompt.focus()},makeDialog:function(o,e){var i,s,r=!1,p=this;this.container.empty(),e.prompt&&(this.prompt=t("<"+(e.prompt_multi_line?'textarea rows="5"':'input type="text"')+' style="margin-bottom:5px;clear:both;" />').addClass((void 0===o.styles.input?"":o.styles.input)+" "+(void 0===e.prompt_class?"":e.prompt_class)).val(e.prompt_default).appendTo(this.container));for(var u=e.buttons[0]&&e.buttons[0]!==n.prototype.options.confirm.buttons[0],c=0;c').addClass((void 0===o.styles.btn?"":o.styles.btn)+" "+(void 0===i.addClass?"":i.addClass)).text(i.text).appendTo(this.container).on("click",function(t){return function(){"function"==typeof t.click&&t.click(o,e.prompt?p.prompt.val():null)}}(i)),e.prompt&&!e.prompt_multi_line&&i.promptTrigger&&this.prompt.keypress(function(t){return function(n){13==n.keyCode&&t.click()}}(s)),o.styles.text&&s.wrapInner(''),o.styles.btnhover&&s.hover(function(t){return function(){t.addClass(o.styles.btnhover)}}(s),function(t){return function(){t.removeClass(o.styles.btnhover)}}(s)),o.styles.btnactive&&s.on("mousedown",function(t){return function(){t.addClass(o.styles.btnactive)}}(s)).on("mouseup",function(t){return function(){t.removeClass(o.styles.btnactive)}}(s)),o.styles.btnfocus&&s.on("focus",function(t){return function(){t.addClass(o.styles.btnfocus)}}(s)).on("blur",function(t){return function(){t.removeClass(o.styles.btnfocus)}}(s)))}},t.extend(n.styling.bootstrap3,{btn:"btn btn-default",input:"form-control"}),t.extend(n.styling.fontawesome,{btn:"btn btn-default",input:"form-control"}),n}); +//# sourceMappingURL=pnotify.confirm.js.map +// Desktop +!function(i,t){"function"==typeof define&&define.amd?define("pnotify.desktop",["jquery","pnotify"],t):"object"==typeof exports&&"undefined"!=typeof module?module.exports=t(require("jquery"),require("./pnotify")):t(i.jQuery,i.PNotify)}("undefined"!=typeof window?window:this,function(i,t){var o,n=function(i,t){return(n="Notification"in window?function(i,t){return new Notification(i,t)}:"mozNotification"in navigator?function(i,t){return navigator.mozNotification.createNotification(i,t.body,t.icon).show()}:"webkitNotifications"in window?function(i,t){return window.webkitNotifications.createNotification(t.icon,i,t.body)}:function(i,t){return null})(i,t)};return t.prototype.options.desktop={desktop:!1,fallback:!0,icon:null,tag:null,title:null,text:null},t.prototype.modules.desktop={genNotice:function(i,t){null===t.icon?this.icon="http://sciactive.com/pnotify/includes/desktop/"+i.options.type+".png":!1===t.icon?this.icon=null:this.icon=t.icon,null!==this.tag&&null===t.tag||(this.tag=null===t.tag?"PNotify-"+Math.round(1e6*Math.random()):t.tag),i.desktop=n(t.title||i.options.title,{icon:this.icon,body:t.text||i.options.text,tag:this.tag}),!("close"in i.desktop)&&"cancel"in i.desktop&&(i.desktop.close=function(){i.desktop.cancel()}),i.desktop.onclick=function(){i.elem.trigger("click")},i.desktop.onclose=function(){"closing"!==i.state&&"closed"!==i.state&&i.remove()}},init:function(i,n){if(n.desktop){if(0!==(o=t.desktop.checkPermission()))return void(n.fallback||(i.options.auto_display=!1));this.genNotice(i,n)}},update:function(i,t,n){0!==o&&t.fallback||!t.desktop||this.genNotice(i,t)},beforeOpen:function(i,t){0!==o&&t.fallback||!t.desktop||i.elem.css({left:"-10000px"}).removeClass("ui-pnotify-in")},afterOpen:function(i,t){0!==o&&t.fallback||!t.desktop||(i.elem.css({left:"-10000px"}).removeClass("ui-pnotify-in"),"show"in i.desktop&&i.desktop.show())},beforeClose:function(i,t){0!==o&&t.fallback||!t.desktop||i.elem.css({left:"-10000px"}).removeClass("ui-pnotify-in")},afterClose:function(i,t){0!==o&&t.fallback||!t.desktop||(i.elem.css({left:"-10000px"}).removeClass("ui-pnotify-in"),"close"in i.desktop&&i.desktop.close())}},t.desktop={permission:function(){"undefined"!=typeof Notification&&"requestPermission"in Notification?Notification.requestPermission():"webkitNotifications"in window&&window.webkitNotifications.requestPermission()},checkPermission:function(){return"undefined"!=typeof Notification&&"permission"in Notification?"granted"===Notification.permission?0:1:"webkitNotifications"in window&&0==window.webkitNotifications.checkPermission()?0:1}},o=t.desktop.checkPermission(),t}); +//# sourceMappingURL=pnotify.desktop.js.map +// History +!function(t,i){"function"==typeof define&&define.amd?define("pnotify.history",["jquery","pnotify"],i):"object"==typeof exports&&"undefined"!=typeof module?module.exports=i(require("jquery"),require("./pnotify")):i(t.jQuery,t.PNotify)}("undefined"!=typeof window?window:this,function(t,i){var e,o;return t(function(){t("body").on("pnotify.history-all",function(){t.each(i.notices,function(){this.modules.history.inHistory&&(this.elem.is(":visible")?this.options.hide&&this.queueRemove():this.open&&this.open())})}).on("pnotify.history-last",function(){var t,e="top"===i.prototype.options.stack.push,o=e?0:-1;do{if(t=-1===o?i.notices.slice(o):i.notices.slice(o,o+1),!t[0])return!1;o=e?o+1:o-1}while(!t[0].modules.history.inHistory||t[0].elem.is(":visible"));t[0].open&&t[0].open()})}),i.prototype.options.history={history:!0,menu:!1,fixed:!0,maxonscreen:1/0,labels:{redisplay:"Redisplay",all:"All",last:"Last"}},i.prototype.modules.history={init:function(i,n){if(i.options.destroy=!1,this.inHistory=n.history,n.menu&&void 0===e){e=t("
",{class:"ui-pnotify-history-container "+i.styles.hi_menu,mouseleave:function(){e.css("top","-"+o+"px")}}).append(t("
",{class:"ui-pnotify-history-header",text:n.labels.redisplay})).append(t(" + +
+
+ + +
+ +
+ +
+

{$ currentStatus $}

+
+ +
+
+ 70% Complete +
+
+ +
+

{% trans "Error message:" %} {$ errorMessage $}

+
+ +
+

{% trans "Website succesfully created." %}

+
+ +
+

{% trans "Could not connect to server. Please refresh this page." %}

+
+ + +
+
+ +
+ +
+ +
+
+ + + + + + + +
+
+
+ + +
+{% endblock %} + diff --git a/vpsManagement/templates/vpsManagement/indexVMM.html b/vpsManagement/templates/vpsManagement/indexVMM.html new file mode 100644 index 000000000..128beceb5 --- /dev/null +++ b/vpsManagement/templates/vpsManagement/indexVMM.html @@ -0,0 +1,68 @@ +{% extends "baseTemplate/indexVMM.html" %} +{% load i18n %} +{% block title %}{% trans "VPS Management - CyberPanel" %}{% endblock %} +{% block content %} + +{% load static %} +{% get_current_language as LANGUAGE_CODE %} + + + +
+
+

{% trans "VPS Management" %}

+

{% trans "Create and delete virtual machines through this page" %}

+
+
+
+

+ {% trans "Available Functions" %} +

+ +
+
+ + +
+ + +{% endblock %} \ No newline at end of file diff --git a/vpsManagement/templates/vpsManagement/listVPS.html b/vpsManagement/templates/vpsManagement/listVPS.html new file mode 100644 index 000000000..da170497e --- /dev/null +++ b/vpsManagement/templates/vpsManagement/listVPS.html @@ -0,0 +1,161 @@ +{% extends "baseTemplate/indexVMM.html" %} +{% load i18n %} +{% block title %}{% trans "List VPS - CyberTron" %}{% endblock %} +{% block content %} + +{% load static %} +{% get_current_language as LANGUAGE_CODE %} + + + +
+ +
+

{% trans "List VPS" %}

+

{% trans "On this page you can launch, list, modify and delete VPS from your server." %}

+
+ +
+
+

+ {% trans "VPSs" %} +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
{% trans 'ID' %}{% trans 'Status' %}{% trans 'IP Address' %}{% trans 'Hostname' %}{% trans 'Package' %}{% trans 'Network Speed' %}{% trans 'Owner' %}{% trans 'Operations' %}Operations
+ + + + + + + +
+ + +
+

{% trans "Error message:" %} {$ errorMessage $}

+
+ +
+

{$ successMessage $}

+
+ +
+

{% trans "Could not connect to server, please refresh this page." %}

+
+ +
+ +
+ + + + +
+ + +
+ + + + + + + + + + + +
+
+
+ +
+ +{% endblock %} \ No newline at end of file diff --git a/vpsManagement/templates/vpsManagement/manageVPS.html b/vpsManagement/templates/vpsManagement/manageVPS.html new file mode 100644 index 000000000..e11e282f1 --- /dev/null +++ b/vpsManagement/templates/vpsManagement/manageVPS.html @@ -0,0 +1,402 @@ +{% extends "baseTemplate/indexVMM.html" %} +{% load i18n %} +{% block title %}{{ hostName }} - CyberPanel{% endblock %} +{% block content %} + +{% load static %} +{% get_current_language as LANGUAGE_CODE %} + + +
+ +
+

{{ hostName }}

+

{% trans "All functions related to a particular VPS." %}

+
+ + {% if not error %} + + +
+ +
+ +

+ {% trans "Virtual Machine Information" %} +

+ + +
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
{% trans "Parameter" %}{% trans "Value" %}
{% trans "Owner" %}{{ owner }}
{% trans "IP Address" %}{{ ipAddr }}
{% trans "Package" %}{{ package }}
{% trans "Disk Used" %}{{ sizeInMB }} MB
{% trans "VNC Port" %}{{ vncPort }}
{% trans "Websocket Port" %}{{ websocketPort }}
+
+ +
+
+
+
+

+ {% trans "Disk Usage" %} +

+
+
+
+
{{ diskUsage }}%
+
+
+ +

+ {% trans "Ram Usage" %} +

+
+
+
+
{{ ramUsage }}%
+
+
+ + +

+ {% trans "Bandwidth Usage" %} +

+
+
+
+
{{ bwUsage }} %
+
+
+ + + +
+ +
+
+
+ +
+
+ + +
+
+ +
+
+ +

+ {% trans "Administrative Tasks" %} +

+ +
+ +
+ + + + + + + + + +
+
+ +
+ +
+ +
+ +
+ + +
+ +
+ + +
+
+ + +
+
+ + + + + +
+
+ +
+ +
+ +
+ +
+ + +
+ +
+ +
+
+ + +
+
+ + + + + + +
+
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+
+ +
+ +
+ +
+
+ +
+ +
+ + +
+
+ +
+ +
+ +
+

{$ currentStatus $}

+
+ +
+
+ 70% Complete +
+
+ +
+

{% trans "Error message:" %} {$ errorMessage $}

+
+ +
+

{% trans "Website succesfully created." %}

+
+ +
+

{% trans "Could not connect to server. Please refresh this page." %}

+
+ + +
+
+ +
+ +
+ +
+
+ + +
+ + + + + + +
+ + + + + +
+ +
+
+
+ +
+
+ +

+ {% trans "Backups/Snapshots/Console" %} +

+ + +
+
+ + + {% else %} + +
+

{{ hostName }}

+
+ + + {% endif %} + + + + +
+ + + +{% endblock %} \ No newline at end of file diff --git a/vpsManagement/templates/vpsManagement/sshKeys.html b/vpsManagement/templates/vpsManagement/sshKeys.html new file mode 100644 index 000000000..c4de5418a --- /dev/null +++ b/vpsManagement/templates/vpsManagement/sshKeys.html @@ -0,0 +1,84 @@ +{% extends "baseTemplate/indexVMM.html" %} +{% load i18n %} +{% block title %}{% trans "SSH Keys - CyberPanel" %}{% endblock %} +{% block content %} + +{% load static %} +{% get_current_language as LANGUAGE_CODE %} + + + +
+
+

{% trans "SSH Keys" %} - {% trans "SSH Docs" %}

+

{% trans "Add or delete SSH keys to be added to virtual machines" %}

+
+ +
+ +
+

+ {% trans "Secure SSH" %} +

+
+ +
+ +
+ +
+ + + + + + + + + + + + + + + + +
{% trans "Key Name" %}{% trans "Key" %}{% trans "Delete" %}
root
+
+
+ +
+
+ +
+
+ +
+
+ +
+ +
+ +
+
+ +
+ +
+ +
+
+ + +
+ +
+
+
+ + +
+ + +{% endblock %} \ No newline at end of file diff --git a/vpsManagement/tests.py b/vpsManagement/tests.py new file mode 100644 index 000000000..5982e6bcd --- /dev/null +++ b/vpsManagement/tests.py @@ -0,0 +1,6 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.test import TestCase + +# Create your tests here. diff --git a/vpsManagement/urls.py b/vpsManagement/urls.py new file mode 100644 index 000000000..d6f03db95 --- /dev/null +++ b/vpsManagement/urls.py @@ -0,0 +1,36 @@ +from django.conf.urls import url +import views + +urlpatterns = [ + + url(r'^$', views.vpsHome, name='vpsHome'), + url(r'^createVPS$', views.createVPS, name='createVPS'), + url(r'^submitVPSCreation$', views.submitVPSCreation, name='submitVPSCreation'), + url(r'^listVPSs$', views.listVPSs, name='listVPSs'), + url(r'^fetchVPS$', views.fetchVPS, name='fetchVPS'), + url(r'^deleteVPS$', views.deleteVPS, name='deleteVPS'), + url(r'^restartVPS$', views.restartVPS, name='restartVPS'), + url(r'^shutdownVPS$', views.shutdownVPS, name='shutdownVPS'), + + url(r'^getVPSDetails$', views.getVPSDetails, name='getVPSDetails'), + url(r'^changeHostname$', views.changeHostname, name='changeHostname'), + url(r'^changeRootPassword$', views.changeRootPassword, name='changeRootPassword'), + url(r'^reInstallOS$', views.reInstallOS, name='reInstallOS'), + + ## + + url(r'^sshKeys$', views.sshKeys, name='sshKeys'), + url(r'^addKey$', views.addKey, name='addKey'), + url(r'^fetchKeys$', views.fetchKeys, name='fetchKeys'), + url(r'^deleteKey$', views.deleteKey, name='deleteKey'), + url(r'^findIPs$', views.findIPs, name='findIPs'), + url(r'^startWebsocketServer$', views.startWebsocketServer, name='startWebsocketServer'), + + ## + + url(r'^(?P(.*))$', views.manageVPS, name='manageVPS'), + + + + +] \ No newline at end of file diff --git a/vpsManagement/views.py b/vpsManagement/views.py new file mode 100644 index 000000000..a8a6a4ce6 --- /dev/null +++ b/vpsManagement/views.py @@ -0,0 +1,164 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.shortcuts import redirect +from loginSystem.views import loadLoginPage +import json +from vpsManager import VPSManager + + +def vpsHome(request): + try: + userID = request.session['userID'] + vmm = VPSManager() + return vmm.vpsHome(request, userID) + except KeyError: + return redirect(loadLoginPage) + +def createVPS(request): + try: + userID = request.session['userID'] + vmm = VPSManager() + return vmm.createVPS(request, userID) + except KeyError: + return redirect(loadLoginPage) + +def submitVPSCreation(request): + try: + userID = request.session['userID'] + vmm = VPSManager() + return vmm.submitVPSCreation(userID, json.loads(request.body)) + except KeyError: + return redirect(loadLoginPage) + +def findIPs(request): + try: + userID = request.session['userID'] + vmm = VPSManager() + return vmm.findIPs(userID, json.loads(request.body)) + except KeyError: + return redirect(loadLoginPage) + +def listVPSs(request): + try: + userID = request.session['userID'] + vmm = VPSManager() + return vmm.listVPSs(request, userID) + except KeyError: + return redirect(loadLoginPage) + +def fetchVPS(request): + try: + userID = request.session['userID'] + vmm = VPSManager() + return vmm.fetchVPS(userID, json.loads(request.body)) + except KeyError: + return redirect(loadLoginPage) + +def deleteVPS(request): + try: + userID = request.session['userID'] + vmm = VPSManager() + return vmm.deleteVPS(userID, json.loads(request.body)) + except KeyError: + return redirect(loadLoginPage) + +def restartVPS(request): + try: + userID = request.session['userID'] + vmm = VPSManager() + return vmm.restartVPS(userID, json.loads(request.body)) + except KeyError: + return redirect(loadLoginPage) + +def shutdownVPS(request): + try: + userID = request.session['userID'] + vmm = VPSManager() + return vmm.shutdownVPS(userID, json.loads(request.body)) + except KeyError: + return redirect(loadLoginPage) + +def manageVPS(request, hostName): + try: + userID = request.session['userID'] + vmm = VPSManager() + return vmm.manageVPS(request, userID, hostName) + except KeyError: + return redirect(loadLoginPage) + +def getVPSDetails(request): + try: + userID = request.session['userID'] + vmm = VPSManager() + return vmm.getVPSDetails(userID, json.loads(request.body)) + except KeyError: + return redirect(loadLoginPage) + +def changeHostname(request): + try: + userID = request.session['userID'] + vmm = VPSManager() + return vmm.changeHostname(userID, json.loads(request.body)) + except KeyError: + return redirect(loadLoginPage) + +def changeRootPassword(request): + try: + userID = request.session['userID'] + vmm = VPSManager() + return vmm.changeRootPassword(userID, json.loads(request.body)) + except KeyError: + return redirect(loadLoginPage) + +def reInstallOS(request): + try: + userID = request.session['userID'] + vmm = VPSManager() + return vmm.reInstallOS(userID, json.loads(request.body)) + except KeyError: + return redirect(loadLoginPage) + +def startWebsocketServer(request): + try: + userID = request.session['userID'] + vmm = VPSManager() + return vmm.startWebsocketServer(userID, json.loads(request.body)) + except KeyError: + return redirect(loadLoginPage) + +## + +def sshKeys(request): + try: + userID = request.session['userID'] + vmm = VPSManager() + return vmm.sshKeys(request, userID) + except KeyError: + return redirect(loadLoginPage) + +def addKey(request): + try: + userID = request.session['userID'] + vmm = VPSManager() + return vmm.addKey(userID, json.loads(request.body)) + except KeyError: + return redirect(loadLoginPage) + +def fetchKeys(request): + try: + userID = request.session['userID'] + vmm = VPSManager() + return vmm.fetchKeys(userID, json.loads(request.body)) + except KeyError: + return redirect(loadLoginPage) + +def deleteKey(request): + try: + userID = request.session['userID'] + vmm = VPSManager() + return vmm.deleteKey(userID, json.loads(request.body)) + except KeyError: + return redirect(loadLoginPage) + + diff --git a/vpsManagement/vpsManager.py b/vpsManagement/vpsManager.py new file mode 100644 index 000000000..aefd6ef31 --- /dev/null +++ b/vpsManagement/vpsManager.py @@ -0,0 +1,660 @@ +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() +from plogical.acl import ACLManager +from plogical.aclVMM import vmmACLManager +from vpsManagement.models import SSHKeys, VPS +from django.shortcuts import render, HttpResponse +from loginSystem.models import Administrator +from CyberTronAPI.virtualMachineAPIKVM import virtualMachineAPI +from CyberTronAPI.cybertron import CyberTron +import json +from hypervisor.models import HyberVisors +from random import randint +import time +from math import ceil +from vpsManagement.models import Snapshots +import subprocess +import shlex + +class VPSManager: + + def vpsHome(self, request = None, userID = None, data = None): + try: + return render(request, 'vpsManagement/indexVMM.html') + except BaseException, msg: + return HttpResponse(str(msg)) + + def createVPS(self, request = None, userID = None, data = None): + try: + currentACL = ACLManager.loadedACL(userID) + if vmmACLManager.currentContextPermission(currentACL, 'createVPS') == 0: + return ACLManager.loadError() + + hvNames = vmmACLManager.findHyperVisorNames(currentACL, userID) + sshKeys = vmmACLManager.findSSHkeyNames(currentACL, userID) + packageNames = vmmACLManager.findAllPackages(currentACL, userID) + ownerNames = ACLManager.loadAllUsers(userID) + + data = {'hvNames': hvNames, 'sshKeys': sshKeys, 'packageNames': packageNames, 'ownerNames': ownerNames} + + return render(request, 'vpsManagement/createVPS.html', data) + + except BaseException, msg: + return HttpResponse(str(msg)) + + def listVPSs(self, request = None, userID = None, data = None): + try: + + currentACL = ACLManager.loadedACL(userID) + vpss = vmmACLManager.findAllVPSOBjs(currentACL, userID) + + pages = float(len(vpss)) / float(10) + pagination = [] + + if pages <= 1.0: + pages = 1 + pagination.append('
  • ') + else: + pages = ceil(pages) + finalPages = int(pages) + 1 + + for i in range(1, finalPages): + pagination.append('
  • ' + str(i) + '
  • ') + + return render(request, 'vpsManagement/listVPS.html', {"pagination": pagination}) + except BaseException, msg: + return HttpResponse(str(msg)) + + def fetchVPS(self, userID = None, data = None): + try: + currentACL = ACLManager.loadedACL(userID) + + pageNumber = int(data['page']) + finalPageNumber = ((pageNumber * 10)) - 10 + endPageNumber = finalPageNumber + 10 + + vpss = vmmACLManager.findAllVPSOBjs(currentACL, userID)[finalPageNumber:endPageNumber] + + json_data = "[" + checker = 0 + + for vps in vpss: + if virtualMachineAPI.isActive(vps.hostName) == 1: + status = 1 + else: + status = 0 + dic = { + 'id': vps.id, + 'status': status, + 'ipAddress': vps.ipAddr.ipAddr, + 'hostname': vps.hostName, + 'package': vps.package.packageName, + 'networkSpeed': vps.networkSpeed, + 'owner': vps.owner.userName + } + + 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 = {'success': 1, 'error_message': "None", "data": json_data, + 'successMessage': 'Successfully fetched!'} + final_json = json.dumps(final_dic) + return HttpResponse(final_json) + + except BaseException, msg: + final_json = json.dumps({'status': 0, 'errorMessage': str(msg)}) + return HttpResponse(final_json) + + def restartVPS(self, userID = None, data = None): + try: + currentACL = ACLManager.loadedACL(userID) + if vmmACLManager.checkOwner(currentACL, userID) == 0: + return ACLManager.loadErrorJson() + + vpsID = data['vpsID'] + vps = VPS.objects.get(id=vpsID) + success, message = virtualMachineAPI.softReboot(vps.hostName) + + if success == 1: + data_ret = {"success": 1, 'error_message': "None", + 'successMessage': 'VPS will restart in background.'} + json_data = json.dumps(data_ret) + return HttpResponse(json_data) + else: + data_ret = {"success": 0, 'error_message': message} + json_data = json.dumps(data_ret) + return HttpResponse(json_data) + except BaseException, msg: + final_json = json.dumps({'status': 0, 'errorMessage': str(msg)}) + return HttpResponse(final_json) + + def shutdownVPS(self, userID = None, data = None): + try: + currentACL = ACLManager.loadedACL(userID) + if vmmACLManager.checkOwner(currentACL, userID) == 0: + return ACLManager.loadErrorJson() + + vpsID = data['vpsID'] + vps = VPS.objects.get(id=vpsID) + success, message = virtualMachineAPI.hardShutdown(vps.hostName) + if success == 1: + data_ret = {"success": 1, 'error_message': "None", + 'successMessage': 'VPS has been stopped.'} + json_data = json.dumps(data_ret) + return HttpResponse(json_data) + else: + data_ret = {"success": 0, 'error_message': message} + json_data = json.dumps(data_ret) + return HttpResponse(json_data) + + except BaseException, msg: + final_json = json.dumps({'status': 0, 'errorMessage': str(msg)}) + return HttpResponse(final_json) + + def getVPSDetails(self, userID = None, data = None): + try: + currentACL = ACLManager.loadedACL(userID) + if vmmACLManager.checkOwner(currentACL, userID) == 0: + return ACLManager.loadErrorJson() + + hostName = data['hostName'] + vps = VPS.objects.get(hostName=hostName) + ## Calculating disk usage percentage + vpsImagePath = '/var/lib/libvirt/images/' + hostName + ".qcow2" + sizeInMB = float(os.path.getsize(vpsImagePath)) / (1024.0 * 1024) + diskUsagePercentage = float(100) / float((int(vps.package.diskSpace.rstrip('GB')) * 1024)) + diskUsagePercentage = float(diskUsagePercentage) * float(sizeInMB) + diskUsagePercentage = int(diskUsagePercentage) + + ## Calculate ram usage percentage + + unUsedRam = virtualMachineAPI.getCurrentUsedRam(hostName) + usedRam = int(vps.package.guaranteedRam.rstrip('MB')) - unUsedRam + + final_dic = {'success': 1, 'error_message': "None", + 'successMessage': 'Successfully fetched!', + 'sizeInMB': int(sizeInMB), + 'diskUsage': diskUsagePercentage} + final_json = json.dumps(final_dic) + return HttpResponse(final_json) + + except BaseException, msg: + final_json = json.dumps({'status': 0, 'errorMessage': str(msg)}) + return HttpResponse(final_json) + + def findIPs(self, userID = None, data = None): + try: + currentACL = ACLManager.loadedACL(userID) + if vmmACLManager.currentContextPermission(currentACL, 'createVPS') == 0: + return ACLManager.loadError() + + hvName = data['hvName'] + hv = HyberVisors.objects.get(hypervisorName=hvName) + allIps = vmmACLManager.jsonIPs(hv) + + final_json = json.dumps({'status': 1, 'errorMessage': "None", 'allIps': allIps}) + return HttpResponse(final_json) + + except BaseException, msg: + final_json = json.dumps({'status': 0, 'errorMessage': str(msg)}) + return HttpResponse(final_json) + + def manageVPS(self, request = None, userID = None, hostName = None): + try: + currentACL = ACLManager.loadedACL(userID) + if vmmACLManager.checkOwner(currentACL, userID) == 0: + return ACLManager.loadError() + + if VPS.objects.filter(hostName=hostName).exists(): + vps = VPS.objects.get(hostName=hostName) + + ## Calculating disk usage percentage + diskUsagePercentage, sizeInMB = virtualMachineAPI.calculateDiskPercentage(hostName, vps.package.diskSpace) + + ## Calculate ram usage percentage + + ramUsagePercentage = virtualMachineAPI.calculateRamPercentage(hostName, vps.package.guaranteedRam) + + ## Calculate bwusage usage percentage + + bwPercentage = virtualMachineAPI.calculateBWPercentage(hostName, vps.package.bandwidth) + + + ## VNC URL + + ipFile = "/etc/cyberpanel/machineIP" + f = open(ipFile) + ipData = f.read() + vncHostIP = ipData.split('\n', 1)[0] + + consoleURL = '/noVNC/vnc.html?host=' + vncHostIP + '&port=570' + str(vps.websocketPort) + '&password=' + vps.vncPassword + + ## Snapshot url + + snapshotsURL = '/backup/' + hostName + '/snapshots' + sshKeys = vmmACLManager.findSSHkeyNames(currentACL, userID) + + + return render(request, 'vpsManagement/manageVPS.html', {'hostName':hostName, + 'owner': vps.owner.userName, + 'ipAddr':vps.ipAddr.ipAddr, + 'package':vps.package.packageName, + 'vncPort':str(vps.vncPort), + 'websocketPort':"570" + str(vps.websocketPort), + 'sizeInMB':int(sizeInMB), + 'diskUsage': diskUsagePercentage, + 'ramUsage':ramUsagePercentage, + 'bwUsage':bwPercentage, + 'consoleURL':consoleURL, + 'snapshotsURL':snapshotsURL, + 'sshKeys' : sshKeys + }) + else: + return render(request, 'vpsManagement/manageVPS.html', + {"error": 1, "hostName": "Virtual Machine with this hostname does not exists."}) + except BaseException, msg: + return HttpResponse(str(msg)) + + def changeHostname(self, userID = None, data = None): + try: + currentACL = ACLManager.loadedACL(userID) + if vmmACLManager.checkOwner(currentACL, userID) == 0: + return ACLManager.loadErrorJson() + + hostName = data['hostName'] + newHostname = data['newHostname'] + + vps = VPS.objects.get(hostName=hostName) + + success, message = virtualMachineAPI.hardShutdown(hostName) + + if success == 1: + virtualMachineAPI.changeHostname(vps.hostName, newHostname) + virtualMachineAPI.softReboot(hostName) + + data_ret = {"success": 1, 'error_message': "None", + 'successMessage': 'VPS Hostname has been successfully changed.'} + json_data = json.dumps(data_ret) + return HttpResponse(json_data) + else: + data_ret = {"success": 0, 'error_message': message} + json_data = json.dumps(data_ret) + return HttpResponse(json_data) + + except BaseException, msg: + final_json = json.dumps({'status': 0, 'errorMessage': str(msg)}) + return HttpResponse(final_json) + + def changeRootPassword(self, userID = None, data = None): + try: + currentACL = ACLManager.loadedACL(userID) + if vmmACLManager.checkOwner(currentACL, userID) == 0: + return ACLManager.loadErrorJson() + + hostName = data['hostName'] + newPassword = data['newPassword'] + + vps = VPS.objects.get(hostName=hostName) + + success, message = virtualMachineAPI.hardShutdown(hostName) + + if success == 1: + virtualMachineAPI.changeRootPassword(vps.hostName, newPassword) + virtualMachineAPI.softReboot(hostName) + + data_ret = {"success": 1, 'error_message': "None", + 'successMessage': 'VPS Root Password has been successfully changed.'} + json_data = json.dumps(data_ret) + return HttpResponse(json_data) + else: + data_ret = {"success": 0, 'error_message': message} + json_data = json.dumps(data_ret) + return HttpResponse(json_data) + + except BaseException, msg: + final_json = json.dumps({'status': 0, 'errorMessage': str(msg)}) + return HttpResponse(final_json) + + def reInstallOS(self, userID = None, data = None): + try: + currentACL = ACLManager.loadedACL(userID) + if vmmACLManager.checkOwner(currentACL, userID) == 0: + return ACLManager.loadErrorJson() + + hostname = data['hostname'] + + vps = VPS.objects.get(hostName=hostname) + + data['tempStatusPath'] = "/home/cyberpanel/" + str(randint(1000, 9999)) + data['vpsOwner'] = vps.owner.userName + + ## + + ipAddr = vps.ipAddr + data['vpsIP'] = ipAddr.ipAddr + ipAddr.used = 0 + ipAddr.save() + + ## + + data['networkSpeed'] = vps.networkSpeed + data['vpsPackage'] = vps.package.packageName + data['vpsID'] = vps.id + + ## First let us delete the VPS + + self.deleteVPS(1, data) + + ## Creating VPS + + ct = CyberTron(data) + ct.start() + time.sleep(2) + + data_ret = {"success": 1, 'error_message': "None", + 'tempStatusPath': data['tempStatusPath']} + json_data = json.dumps(data_ret) + return HttpResponse(json_data) + + except BaseException, msg: + final_json = json.dumps({'status': 0, 'errorMessage': str(msg)}) + return HttpResponse(final_json) + + def deleteVPS(self, userID = None, data = None): + try: + currentACL = ACLManager.loadedACL(userID) + if vmmACLManager.currentContextPermission(currentACL, 'deleteVPS') == 0: + return ACLManager.loadErrorJson() + + vpsID = data['vpsID'] + + vps = VPS.objects.get(id=vpsID) + ip = vps.ipAddr + ip.used = 0 + ip.save() + hostName = vps.hostName + vps.delete() + + virtualMachineAPI.deleteVirtualMachine(hostName) + + interfaceFile = "/etc/cyberpanel/interfaceName" + f = open(interfaceFile) + interfaceData = f.read() + interfaceName = interfaceData.split('\n', 1)[0] + + virtualMachineAPI.removeVMSpeedLimit(str(vpsID), interfaceName) + + + data_ret = {"success": 1, 'error_message': "None", + 'successMessage': 'VPS Successfully Deleted!'} + json_data = json.dumps(data_ret) + return HttpResponse(json_data) + + except BaseException, msg: + final_json = json.dumps({'status': 0, 'errorMessage': str(msg)}) + return HttpResponse(final_json) + + def sshKeys(self, request = None, userID = None, data = None): + try: + currentACL = ACLManager.loadedACL(userID) + if vmmACLManager.currentContextPermission(currentACL, 'sshKeys') == 0: + return ACLManager.loadError() + + return render(request, 'vpsManagement/sshKeys.html') + + except BaseException, msg: + return HttpResponse(str(msg)) + + def addKey(self, userID = None, data = None): + try: + currentACL = ACLManager.loadedACL(userID) + if vmmACLManager.currentContextPermission(currentACL, 'sshKeys') == 0: + return ACLManager.loadErrorJson() + + keyName = data['keyName'] + keyData = data['keyData'] + + admin = Administrator.objects.get(pk=userID) + + newKey = SSHKeys(owner=admin, keyName=keyName, key=keyData) + newKey.save() + + final_json = json.dumps({'status': 1, 'errorMessage': "None"}) + return HttpResponse(final_json) + + except BaseException, msg: + final_json = json.dumps({'status': 0, 'errorMessage': str(msg)}) + return HttpResponse(final_json) + + def fetchKeys(self, userID = None, data = None): + try: + currentACL = ACLManager.loadedACL(userID) + if vmmACLManager.currentContextPermission(currentACL, 'sshKeys') == 0: + return ACLManager.loadErrorJson() + + sshKeys = vmmACLManager.fetchSSHkeys(currentACL, userID) + + final_json = json.dumps({'status': 1, 'errorMessage': "None", 'sshKeys': sshKeys}) + return HttpResponse(final_json) + + except BaseException, msg: + final_json = json.dumps({'status': 0, 'errorMessage': str(msg)}) + return HttpResponse(final_json) + + def deleteKey(self, userID = None, data = None): + try: + currentACL = ACLManager.loadedACL(userID) + if vmmACLManager.currentContextPermission(currentACL, 'sshKeys') == 0: + return ACLManager.loadErrorJson() + + delKey = SSHKeys.objects.get(keyName=data['keyName']) + delKey.delete() + + final_json = json.dumps({'status': 1, 'errorMessage': "None"}) + return HttpResponse(final_json) + + except BaseException, msg: + final_json = json.dumps({'status': 0, 'errorMessage': str(msg)}) + return HttpResponse(final_json) + + def submitVPSCreation(self, userID = None, data = None): + try: + + currentACL = ACLManager.loadedACL(userID) + if vmmACLManager.currentContextPermission(currentACL, 'createVPS') == 0: + return ACLManager.loadErrorJson() + + ## Creating VPS + + data['tempStatusPath'] = "/home/cyberpanel/" + str(randint(1000, 9999)) + + ct = CyberTron(data) + ct.start() + time.sleep(2) + + data_ret = {"success": 1, 'error_message': "None", + 'tempStatusPath': data['tempStatusPath']} + json_data = json.dumps(data_ret) + return HttpResponse(json_data) + + except BaseException, msg: + virtualMachineAPI.deleteVirtualMachine(data['hostname']) + data_ret = {"success": 0, + 'error_message': str(msg)} + json_data = json.dumps(data_ret) + return HttpResponse(json_data) + + def createSnapshots(self, request = None, userID = None, hostName = None): + try: + currentACL = ACLManager.loadedACL(userID) + if vmmACLManager.checkOwner(currentACL, userID) == 0: + return ACLManager.loadErrorJson() + + return render(request, 'backup/createSnapshots.html', {'hostName': hostName}) + + except BaseException, msg: + return HttpResponse(str(msg)) + + def fetchCurrentSnapshots(self, userID = None, data = None): + try: + currentACL = ACLManager.loadedACL(userID) + if vmmACLManager.checkOwner(currentACL, userID) == 0: + return ACLManager.loadErrorJson() + + hostName = data['hostName'] + + vps = VPS.objects.get(hostName=hostName) + snapshots = vps.snapshots_set.all() + + json_data = "[" + checker = 0 + + for snapshot in snapshots: + dic = { + 'id': snapshot.id, + 'hostname': hostName, + 'name': snapshot.name, + 'creationTime': snapshot.creationTime, + } + + 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 = {'success': 1, 'error_message': "None", "data": json_data, + 'successMessage': 'Successfully fetched!'} + final_json = json.dumps(final_dic) + return HttpResponse(final_json) + + except BaseException, msg: + final_json = json.dumps({'status': 0, 'errorMessage': str(msg)}) + return HttpResponse(final_json) + + def submitSnapshotCreation(self, userID = None, data = None): + try: + currentACL = ACLManager.loadedACL(userID) + if vmmACLManager.checkOwner(currentACL, userID) == 0: + return ACLManager.loadErrorJson() + + hostName = data['hostName'] + snapshotName = data['snapshotName'] + + vps = VPS.objects.get(hostName=hostName) + + if Snapshots.objects.filter(vps=vps, name=snapshotName).count() > 0: + data_ret = {"success": 0, + 'error_message': 'Snapshot with this name already exists for this Virtual Machine.'} + json_data = json.dumps(data_ret) + return HttpResponse(json_data) + + virtualMachineAPI.createSnapshot(hostName, snapshotName) + + newSnapshot = Snapshots(vps=vps, name=snapshotName, creationTime=time.strftime("%I-%M-%S-%a-%b-%Y")) + newSnapshot.save() + + data_ret = {"success": 1, 'error_message': "None", + 'successMessage': 'Snapshot Successfully Created!'} + json_data = json.dumps(data_ret) + return HttpResponse(json_data) + + except BaseException, msg: + final_json = json.dumps({'status': 0, 'errorMessage': str(msg)}) + return HttpResponse(final_json) + + def deletSnapshot(self, userID = None, data = None): + try: + currentACL = ACLManager.loadedACL(userID) + if vmmACLManager.checkOwner(currentACL, userID) == 0: + return ACLManager.loadErrorJson() + + hostName = data['hostName'] + snapshotName = data['snapshotName'] + + virtualMachineAPI.deleteSnapshot(hostName, snapshotName) + + newSnapshot = Snapshots.objects.get(name=snapshotName) + newSnapshot.delete() + + data_ret = {"success": 1, 'error_message': "None", + 'successMessage': 'Snapshot Successfully Deleted!'} + json_data = json.dumps(data_ret) + return HttpResponse(json_data) + + except BaseException, msg: + final_json = json.dumps({'status': 0, 'errorMessage': str(msg)}) + return HttpResponse(final_json) + + def revertToSnapshot(self, userID = None, data = None): + try: + currentACL = ACLManager.loadedACL(userID) + if vmmACLManager.checkOwner(currentACL, userID) == 0: + return ACLManager.loadErrorJson() + + hostName = data['hostName'] + snapshotName = data['snapshotName'] + + virtualMachineAPI.revertToSnapshot(hostName, snapshotName) + + data_ret = {"success": 1, 'error_message': "None", + 'successMessage': 'Successfully reverted Virtual Machine to: ' + snapshotName} + json_data = json.dumps(data_ret) + return HttpResponse(json_data) + + except BaseException, msg: + final_json = json.dumps({'status': 0, 'errorMessage': str(msg)}) + return HttpResponse(final_json) + + + def startWebsocketServer(self, userID = None, data = None): + try: + currentACL = ACLManager.loadedACL(userID) + if vmmACLManager.checkOwner(currentACL, userID) == 0: + return ACLManager.loadErrorJson() + + vpsHostname = data['hostname'] + + vps = VPS.objects.get(hostName=vpsHostname) + + hostnameFile = "/etc/cyberpanel/hostname" + hostname = open(hostnameFile, 'r') + actualHostName = hostname.read() + actualHostName = actualHostName.split('\n', 1)[0] + + ipFile = "/etc/cyberpanel/machineIP" + f = open(ipFile) + ipData = f.read() + vncHostIP = ipData.split('\n', 1)[0] + + frontVNCPort = str(vps.websocketPort + 9000) + backVNCPort = str(vps.websocketPort + 5900) + + + command = '/usr/local/lscp/cyberpanel/noVNC/utils/launch.sh --listen ' + frontVNCPort + ' --vnc ' \ + + vncHostIP + ':' + backVNCPort + ' --cert /usr/local/lscp/cyberpanel/noVNC/utils/self.pem' + subprocess.Popen(shlex.split(command)) + + finalURL = 'https://' + actualHostName + ":" + frontVNCPort + "/vnc.html?host=" + actualHostName + \ + "&port=" + frontVNCPort + '&password=' + vps.vncPassword + "&autoconnect" + + + data_ret = {"success": 1, 'error_message': "None", + 'finalURL': finalURL} + json_data = json.dumps(data_ret) + return HttpResponse(json_data) + + except BaseException, msg: + final_json = json.dumps({'status': 0, 'errorMessage': str(msg)}) + return HttpResponse(final_json) + diff --git a/websiteFunctions/templates/websiteFunctions/createWebsite.html b/websiteFunctions/templates/websiteFunctions/createWebsite.html index c347656a4..f8038e462 100644 --- a/websiteFunctions/templates/websiteFunctions/createWebsite.html +++ b/websiteFunctions/templates/websiteFunctions/createWebsite.html @@ -121,7 +121,6 @@
    -