diff --git a/CyberCP/settings.py b/CyberCP/settings.py
index c2b96314a..23c296dd6 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 = ['*']
@@ -62,9 +62,7 @@ INSTALLED_APPS = [
'pluginHolder',
'emailPremium',
'emailMarketing',
- 'cloudAPI',
- 'highAvailability',
- 's3Backups'
+ 'dockerManager'
]
MIDDLEWARE = [
@@ -109,15 +107,15 @@ DATABASES = {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'cyberpanel',
'USER': 'cyberpanel',
- 'PASSWORD': 'Bz9gF7Hr7X4RtD',
- 'HOST': '127.0.0.1',
- 'PORT':'3307'
+ 'PASSWORD': 'a9AwLb7zY7ZwCd',
+ 'HOST': 'localhost',
+ 'PORT': '',
},
'rootdb': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'mysql',
'USER': 'root',
- 'PASSWORD': 'sXm5VlRaAsXkDd',
+ 'PASSWORD': '3bL8X7wGo0kT3b',
'HOST': 'localhost',
'PORT': '',
},
diff --git a/CyberCP/urls.py b/CyberCP/urls.py
index bb6952ac6..4c81d06f2 100644
--- a/CyberCP/urls.py
+++ b/CyberCP/urls.py
@@ -21,6 +21,7 @@ urlpatterns = [
url(r'^', include('loginSystem.urls')),
url(r'^packages/',include('packages.urls')),
url(r'^websites/',include('websiteFunctions.urls')),
+ url(r'^docker/',include('dockerManager.urls')),
url(r'^tuning/',include('tuning.urls')),
url(r'^ftp/',include('ftp.urls')),
url(r'^serverstatus/',include('serverStatus.urls')),
diff --git a/backup/migrations/0001_initial.py b/backup/migrations/0001_initial.py
new file mode 100644
index 000000000..971731f5a
--- /dev/null
+++ b/backup/migrations/0001_initial.py
@@ -0,0 +1,70 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11 on 2019-01-07 12:43
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ initial = True
+
+ dependencies = [
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='DBUsers',
+ fields=[
+ ('host', models.CharField(db_column='Host', max_length=60, primary_key=True, serialize=False)),
+ ('user', models.CharField(db_column='User', max_length=16)),
+ ('password', models.CharField(db_column='Password', max_length=41)),
+ ('select_priv', models.CharField(db_column='Select_priv', max_length=1)),
+ ('insert_priv', models.CharField(db_column='Insert_priv', max_length=1)),
+ ('update_priv', models.CharField(db_column='Update_priv', max_length=1)),
+ ('delete_priv', models.CharField(db_column='Delete_priv', max_length=1)),
+ ('create_priv', models.CharField(db_column='Create_priv', max_length=1)),
+ ('drop_priv', models.CharField(db_column='Drop_priv', max_length=1)),
+ ('reload_priv', models.CharField(db_column='Reload_priv', max_length=1)),
+ ('shutdown_priv', models.CharField(db_column='Shutdown_priv', max_length=1)),
+ ('process_priv', models.CharField(db_column='Process_priv', max_length=1)),
+ ('file_priv', models.CharField(db_column='File_priv', max_length=1)),
+ ('grant_priv', models.CharField(db_column='Grant_priv', max_length=1)),
+ ('references_priv', models.CharField(db_column='References_priv', max_length=1)),
+ ('index_priv', models.CharField(db_column='Index_priv', max_length=1)),
+ ('alter_priv', models.CharField(db_column='Alter_priv', max_length=1)),
+ ('show_db_priv', models.CharField(db_column='Show_db_priv', max_length=1)),
+ ('super_priv', models.CharField(db_column='Super_priv', max_length=1)),
+ ('create_tmp_table_priv', models.CharField(db_column='Create_tmp_table_priv', max_length=1)),
+ ('lock_tables_priv', models.CharField(db_column='Lock_tables_priv', max_length=1)),
+ ('execute_priv', models.CharField(db_column='Execute_priv', max_length=1)),
+ ('repl_slave_priv', models.CharField(db_column='Repl_slave_priv', max_length=1)),
+ ('repl_client_priv', models.CharField(db_column='Repl_client_priv', max_length=1)),
+ ('create_view_priv', models.CharField(db_column='Create_view_priv', max_length=1)),
+ ('show_view_priv', models.CharField(db_column='Show_view_priv', max_length=1)),
+ ('create_routine_priv', models.CharField(db_column='Create_routine_priv', max_length=1)),
+ ('alter_routine_priv', models.CharField(db_column='Alter_routine_priv', max_length=1)),
+ ('create_user_priv', models.CharField(db_column='Create_user_priv', max_length=1)),
+ ('event_priv', models.CharField(db_column='Event_priv', max_length=1)),
+ ('trigger_priv', models.CharField(db_column='Trigger_priv', max_length=1)),
+ ('create_tablespace_priv', models.CharField(db_column='Create_tablespace_priv', max_length=1)),
+ ('ssl_type', models.CharField(max_length=9)),
+ ('ssl_cipher', models.TextField()),
+ ('x509_issuer', models.TextField()),
+ ('x509_subject', models.TextField()),
+ ('max_questions', models.IntegerField()),
+ ('max_updates', models.IntegerField()),
+ ('max_connections', models.IntegerField()),
+ ('max_user_connections', models.IntegerField()),
+ ('plugin', models.CharField(max_length=64)),
+ ('authentication_string', models.TextField()),
+ ],
+ options={
+ 'db_table': 'user',
+ },
+ ),
+ migrations.AlterUniqueTogether(
+ name='dbusers',
+ unique_together=set([('host', 'user')]),
+ ),
+ ]
diff --git a/baseTemplate/migrations/0001_initial.py b/baseTemplate/migrations/0001_initial.py
new file mode 100644
index 000000000..8a21783bb
--- /dev/null
+++ b/baseTemplate/migrations/0001_initial.py
@@ -0,0 +1,24 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11 on 2019-01-07 12:43
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ initial = True
+
+ dependencies = [
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='version',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('currentVersion', models.CharField(max_length=50)),
+ ('build', models.IntegerField()),
+ ],
+ ),
+ ]
diff --git a/baseTemplate/templates/baseTemplate/index.html b/baseTemplate/templates/baseTemplate/index.html
index 98612c206..77c8fc2c7 100644
--- a/baseTemplate/templates/baseTemplate/index.html
+++ b/baseTemplate/templates/baseTemplate/index.html
@@ -666,6 +666,7 @@
+
diff --git a/databases/migrations/0001_initial.py b/databases/migrations/0001_initial.py
new file mode 100644
index 000000000..ac622d14b
--- /dev/null
+++ b/databases/migrations/0001_initial.py
@@ -0,0 +1,27 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11 on 2019-01-07 12:43
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+ initial = True
+
+ dependencies = [
+ ('websiteFunctions', '0001_initial'),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='Databases',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('dbName', models.CharField(max_length=50, unique=True)),
+ ('dbUser', models.CharField(max_length=50, unique=True)),
+ ('website', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='websiteFunctions.Websites')),
+ ],
+ ),
+ ]
diff --git a/dns/migrations/0001_initial.py b/dns/migrations/0001_initial.py
new file mode 100644
index 000000000..91824de73
--- /dev/null
+++ b/dns/migrations/0001_initial.py
@@ -0,0 +1,125 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11 on 2019-01-07 12:43
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+ initial = True
+
+ dependencies = [
+ ('loginSystem', '0001_initial'),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='Comments',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('domain_id', models.IntegerField()),
+ ('name', models.CharField(max_length=255)),
+ ('type', models.CharField(max_length=10)),
+ ('modified_at', models.IntegerField()),
+ ('account', models.CharField(max_length=40)),
+ ('comment', models.CharField(max_length=64000)),
+ ],
+ options={
+ 'db_table': 'comments',
+ },
+ ),
+ migrations.CreateModel(
+ name='Cryptokeys',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('domain_id', models.IntegerField()),
+ ('flags', models.IntegerField()),
+ ('active', models.IntegerField(blank=True, null=True)),
+ ('content', models.TextField(blank=True, null=True)),
+ ],
+ options={
+ 'db_table': 'cryptokeys',
+ },
+ ),
+ migrations.CreateModel(
+ name='Domainmetadata',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('domain_id', models.IntegerField()),
+ ('kind', models.CharField(blank=True, max_length=32, null=True)),
+ ('content', models.TextField(blank=True, null=True)),
+ ],
+ options={
+ 'db_table': 'domainmetadata',
+ },
+ ),
+ migrations.CreateModel(
+ name='Domains',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('name', models.CharField(max_length=255, unique=True)),
+ ('master', models.CharField(blank=True, max_length=128, null=True)),
+ ('last_check', models.IntegerField(blank=True, null=True)),
+ ('type', models.CharField(max_length=6)),
+ ('notified_serial', models.IntegerField(blank=True, null=True)),
+ ('account', models.CharField(blank=True, max_length=40, null=True)),
+ ('admin', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='loginSystem.Administrator')),
+ ],
+ options={
+ 'db_table': 'domains',
+ },
+ ),
+ migrations.CreateModel(
+ name='Records',
+ fields=[
+ ('id', models.BigAutoField(primary_key=True, serialize=False)),
+ ('domain_id', models.IntegerField(blank=True, null=True)),
+ ('name', models.CharField(blank=True, max_length=255, null=True)),
+ ('type', models.CharField(blank=True, max_length=10, null=True)),
+ ('content', models.CharField(blank=True, max_length=64000, null=True)),
+ ('ttl', models.IntegerField(blank=True, null=True)),
+ ('prio', models.IntegerField(blank=True, null=True)),
+ ('change_date', models.IntegerField(blank=True, null=True)),
+ ('disabled', models.IntegerField(blank=True, null=True)),
+ ('ordername', models.CharField(blank=True, max_length=255, null=True)),
+ ('auth', models.IntegerField(blank=True, null=True)),
+ ('domainOwner', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='dns.Domains')),
+ ],
+ options={
+ 'db_table': 'records',
+ },
+ ),
+ migrations.CreateModel(
+ name='Supermasters',
+ fields=[
+ ('ip', models.CharField(max_length=64, primary_key=True, serialize=False)),
+ ('nameserver', models.CharField(max_length=255)),
+ ('account', models.CharField(max_length=40)),
+ ],
+ options={
+ 'db_table': 'supermasters',
+ },
+ ),
+ migrations.CreateModel(
+ name='Tsigkeys',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('name', models.CharField(blank=True, max_length=255, null=True)),
+ ('algorithm', models.CharField(blank=True, max_length=50, null=True)),
+ ('secret', models.CharField(blank=True, max_length=255, null=True)),
+ ],
+ options={
+ 'db_table': 'tsigkeys',
+ },
+ ),
+ migrations.AlterUniqueTogether(
+ name='tsigkeys',
+ unique_together=set([('name', 'algorithm')]),
+ ),
+ migrations.AlterUniqueTogether(
+ name='supermasters',
+ unique_together=set([('ip', 'nameserver')]),
+ ),
+ ]
diff --git a/dockerManager/__init__.py b/dockerManager/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/dockerManager/admin.py b/dockerManager/admin.py
new file mode 100644
index 000000000..13be29d96
--- /dev/null
+++ b/dockerManager/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/dockerManager/apps.py b/dockerManager/apps.py
new file mode 100644
index 000000000..b8b50bdb2
--- /dev/null
+++ b/dockerManager/apps.py
@@ -0,0 +1,8 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.apps import AppConfig
+
+
+class DockermanagerConfig(AppConfig):
+ name = 'dockerManager'
diff --git a/dockerManager/decorators.py b/dockerManager/decorators.py
new file mode 100644
index 000000000..44baf3280
--- /dev/null
+++ b/dockerManager/decorators.py
@@ -0,0 +1,47 @@
+from django.shortcuts import render,redirect
+from loginSystem.models import Administrator
+import os
+import docker
+import json
+from django.http import HttpResponse
+from loginSystem.views import loadLoginPage
+
+def preDockerRun(function):
+ def wrap(request, *args, **kwargs):
+
+ try:
+ val = request.session['userID']
+ except KeyError:
+ return redirect(loadLoginPage)
+
+ admin = Administrator.objects.get(pk=val)
+
+ if request.method == "POST":
+ isPost = True
+ else:
+ isPost = False
+
+ # check if docker is installed
+ dockerInstallPath = '/usr/bin/docker'
+ if not os.path.exists(dockerInstallPath):
+ if isPost:
+ data_ret = {'status': 0, 'error_message': 'Docker not installed'}
+ json_data = json.dumps(data_ret)
+ return HttpResponse(json_data)
+ else:
+ return render(request, 'dockerManager/install.html', {'status':admin.type, 'conErr':0})
+
+ # Check if docker is running and we are able to connect
+ try:
+ client = docker.from_env()
+ client.ping()
+ except:
+ if isPost:
+ data_ret = {'status': 0, 'error_message': 'Docker daemon not running or not responsive'}
+ json_data = json.dumps(data_ret)
+ return HttpResponse(json_data)
+ else:
+ return render(request, 'dockerManager/install.html', {'status':admin.type, 'conErr':1})
+
+ return function(request, *args, **kwargs)
+ return wrap
\ No newline at end of file
diff --git a/dockerManager/models.py b/dockerManager/models.py
new file mode 100644
index 000000000..b54527d4e
--- /dev/null
+++ b/dockerManager/models.py
@@ -0,0 +1,17 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.db import models
+from loginSystem.models import Administrator
+
+# Create your models here.
+class Containers(models.Model):
+ name = models.CharField(max_length=50,unique=True)
+ cid = models.CharField(max_length=64, default='')
+ admin = models.ForeignKey(Administrator)
+ image = models.CharField(max_length=50, default='unknown')
+ tag = models.CharField(max_length=50, default='unknown')
+ memory = models.IntegerField(default=0)
+ ports = models.TextField(default="{}")
+ env = models.TextField(default="{}")
+ startOnReboot = models.IntegerField(default=0)
diff --git a/dockerManager/pluginManager.py b/dockerManager/pluginManager.py
new file mode 100644
index 000000000..60a64e7ca
--- /dev/null
+++ b/dockerManager/pluginManager.py
@@ -0,0 +1,12 @@
+from signals import *
+from plogical.pluginManagerGlobal import pluginManagerGlobal
+
+class pluginManager:
+
+ @staticmethod
+ def preDockerInstallation(request):
+ return pluginManagerGlobal.globalPlug(request, preDockerInstallation)
+
+ @staticmethod
+ def postDockerInstallation(request, response):
+ return pluginManagerGlobal.globalPlug(request, postDockerInstallation, response)
\ No newline at end of file
diff --git a/dockerManager/signals.py b/dockerManager/signals.py
new file mode 100644
index 000000000..81a43e415
--- /dev/null
+++ b/dockerManager/signals.py
@@ -0,0 +1,10 @@
+# The world is a prison for the believer.
+## https://www.youtube.com/watch?v=DWfNYztUM1U
+
+from django.dispatch import Signal
+
+## This event is fired before CyberPanel core start installation of Docker
+preDockerInstallation = Signal(providing_args=["request"])
+
+## This event is fired after CyberPanel core finished intallation of Docker.
+postDockerInstallation = Signal(providing_args=["request", "response"])
diff --git a/dockerManager/static/dockerManager/dockerManager.js b/dockerManager/static/dockerManager/dockerManager.js
new file mode 100644
index 000000000..1faee184a
--- /dev/null
+++ b/dockerManager/static/dockerManager/dockerManager.js
@@ -0,0 +1,1106 @@
+app.controller('installDocker', function($scope,$http) {
+ $scope.installDockerStatus = true;
+ $scope.installDocker = function(){
+ $scope.installDockerStatus = false;
+ url = "/docker/installDocker";
+ var data = {};
+ var config = {
+ headers : {
+ 'X-CSRFToken': getCookie('csrftoken')
+ }
+ };
+
+ $http.post(url, data,config).then(ListInitialDatas, cantLoadInitialDatas);
+
+ function ListInitialDatas(response) {
+ if (response.data.installDockerStatus === 1)
+ {
+ new PNotify({
+ title: 'Docker installed',
+ text: 'Reloading...',
+ type: 'success'
+ });
+ location.reload();
+ }
+ else{
+ new PNotify({
+ title: 'Failed to complete request',
+ text: response.data.error,
+ type: 'error'
+ });
+ }
+ $scope.installDockerStatus = true;
+
+ }
+ function cantLoadInitialDatas(response) {
+ $scope.installDockerStatus = true;
+ new PNotify({
+ title: 'Failed to complete request',
+ type: 'error'
+ });
+ }
+ }
+});
+
+/* Java script code for docker management */
+var delayTimer = null;
+
+app.controller('dockerImages', function($scope,$http) {
+ $scope.tagList = [];
+ $scope.imageTag = {};
+});
+
+/* Java script code to install Container */
+
+app.controller('runContainer', function($scope,$http) {
+ $scope.containerCreationLoading = true;
+ $scope.installationDetailsForm = false;
+ $scope.installationProgress = true;
+ $scope.errorMessageBox = true;
+ $scope.success = true;
+ $scope.couldNotConnect = true;
+ $scope.goBackDisable = true;
+
+ $scope.addEnvField = function() {
+ var countEnv = Object.keys($scope.envList).length;
+ $scope.envList[countEnv+1] = {'name':'', 'value':''};
+ }
+
+ var statusFile;
+
+ $scope.createContainer = function(){
+
+ console.log($scope.iport);
+ console.log($scope.portType);
+
+ $scope.containerCreationLoading = true;
+ $scope.installationDetailsForm = true;
+ $scope.installationProgress = false;
+ $scope.errorMessageBox = true;
+ $scope.success = true;
+ $scope.couldNotConnect = true;
+ $scope.goBackDisable = true;
+
+ $scope.currentStatus = "Starting creation..";
+
+ url = "/docker/submitContainerCreation";
+
+ var name = $scope.name;
+ var tag = $scope.tag;
+ var memory = $scope.memory;
+ var dockerOwner = $scope.dockerOwner;
+ var image = $scope.image;
+ var numberOfEnv = Object.keys($scope.envList).length;
+
+ var data = {
+ name: name,
+ tag: tag,
+ memory: memory,
+ dockerOwner: dockerOwner,
+ image: image,
+ envList: $scope.envList
+
+ };
+
+ $.each($scope.portType, function( port, protocol ) {
+ data[port + "/" + protocol] = $scope.eport[port];
+ });
+
+ console.log(data)
+
+ var config = {
+ headers : {
+ 'X-CSRFToken': getCookie('csrftoken')
+ }
+ };
+
+ $http.post(url, data,config).then(ListInitialDatas, cantLoadInitialDatas);
+
+
+ function ListInitialDatas(response) {
+
+ if (response.data.createContainerStatus === 1)
+ {
+ $scope.currentStatus = "Successful. Redirecting...";
+ window.location.href = "/docker/view/" + $scope.name
+ }
+ else{
+
+ $scope.containerCreationLoading = true;
+ $scope.installationDetailsForm = true;
+ $scope.installationProgress = false;
+ $scope.errorMessageBox = false;
+ $scope.success = true;
+ $scope.couldNotConnect = true;
+ $scope.goBackDisable = false;
+
+ $scope.errorMessage = response.data.error_message;
+ }
+
+
+
+ }
+ function cantLoadInitialDatas(response) {
+
+ $scope.containerCreationLoading = true;
+ $scope.installationDetailsForm = true;
+ $scope.installationProgress = false;
+ $scope.errorMessageBox = true;
+ $scope.success = true;
+ $scope.couldNotConnect = false;
+ $scope.goBackDisable = false;
+
+ }
+ };
+ $scope.goBack = function () {
+ $scope.containerCreationLoading = true;
+ $scope.installationDetailsForm = false;
+ $scope.installationProgress = true;
+ $scope.errorMessageBox = true;
+ $scope.success = true;
+ $scope.couldNotConnect = true;
+ $scope.goBackDisable = true;
+ $("#installProgress").css("width", "0%");
+ };
+
+});
+
+/* Javascript code for listing containers */
+
+
+app.controller('listContainers', function($scope,$http) {
+ $scope.activeLog = "";
+ $scope.assignActive = "";
+
+ $scope.assignContainer = function(name){
+ $("#assign").modal("show");
+ $scope.assignActive = name;
+ }
+
+ $scope.submitAssignContainer = function(){
+ url = "/docker/assignContainer";
+
+ var data = {name: $scope.assignActive, admin: $scope.dockerOwner};
+
+ var config = {
+ headers : {
+ 'X-CSRFToken': getCookie('csrftoken')
+ }
+ };
+
+ $http.post(url, data,config).then(ListInitialData, cantLoadInitialData);
+
+ function ListInitialData(response) {
+
+ if (response.data.assignContainerStatus === 1) {
+ new PNotify({
+ title: 'Container assigned successfully',
+ type: 'success'
+ });
+ window.location.href = '/docker/listContainers';
+ }
+ else
+ {
+ new PNotify({
+ title: 'Unable to complete request',
+ text: response.data.error_message,
+ type: 'error'
+ });
+ }
+ $("#assign").modal("hide");
+ }
+ function cantLoadInitialData(response) {
+ console.log("not good");
+ new PNotify({
+ title: 'Unable to complete request',
+ type: 'error'
+ });
+ $("#assign").modal("hide");
+ }
+ }
+
+ $scope.delContainer = function(name, unlisted=false){
+ (new PNotify({
+ title: 'Confirmation Needed',
+ text: 'Are you sure?',
+ icon: 'fa fa-question-circle',
+ hide: false,
+ confirm: {
+ confirm: true
+ },
+ buttons: {
+ closer: false,
+ sticker: false
+ },
+ history: {
+ history: false
+ }
+ })).get().on('pnotify.confirm', function() {
+ $('#imageLoading').show();
+ url = "/docker/delContainer";
+
+ var data = {name: name, unlisted: unlisted};
+
+ var config = {
+ headers : {
+ 'X-CSRFToken': getCookie('csrftoken')
+ }
+ };
+
+ $http.post(url, data,config).then(ListInitialData, cantLoadInitialData);
+
+
+ function ListInitialData(response) {
+ console.log(response);
+
+ if (response.data.delContainerStatus === 1) {
+ location.reload();
+ }
+ else if (response.data.delContainerStatus == 2) {
+ (new PNotify({
+ title: response.data.error_message,
+ text: 'Delete anyway?',
+ icon: 'fa fa-question-circle',
+ hide: false,
+ confirm: {
+ confirm: true
+ },
+ buttons: {
+ closer: false,
+ sticker: false
+ },
+ history: {
+ history: false
+ }
+ })).get().on('pnotify.confirm', function() {
+ url = "/docker/delContainer";
+
+ var data = {name: name, unlisted: unlisted, force: 1};
+
+ var config = {
+ headers : {
+ 'X-CSRFToken': getCookie('csrftoken')
+ }
+ };
+
+ $http.post(url, data,config).then(ListInitialData, cantLoadInitialData);
+
+
+ function ListInitialData(response) {
+ if (response.data.delContainerStatus === 1) {
+ location.reload();
+ }
+ else {
+ $("#listFail").fadeIn();
+ $scope.errorMessage = response.data.error_message;
+ }
+ $('#imageLoading').hide();
+ }
+ function cantLoadInitialData(response) {
+ $('#imageLoading').hide();
+ }
+ })
+ }
+ else
+ {
+ $("#listFail").fadeIn();
+ $scope.errorMessage = response.data.error_message;
+ }
+ $('#imageLoading').hide();
+ }
+ function cantLoadInitialData(response) {
+ $('#imageLoading').hide();
+ }
+ })
+ }
+
+ $scope.showLog = function(name, refresh = false){
+ $scope.logs = "";
+ if (refresh === false){
+ $('#logs').modal('show');
+ $scope.activeLog = name;
+ }
+ else {
+ name = $scope.activeLog;
+ }
+ console.log(name)
+ $scope.logs = "Loading...";
+
+ url = "/docker/getContainerLogs";
+
+ var data = {name: name};
+
+ var config = {
+ headers : {
+ 'X-CSRFToken': getCookie('csrftoken')
+ }
+ };
+
+ $http.post(url, data,config).then(ListInitialData, cantLoadInitialData);
+
+
+ function ListInitialData(response) {
+ console.log(response);
+
+ if (response.data.containerLogStatus === 1) {
+ $scope.logs = response.data.containerLog;
+ }
+ else
+ {
+ new PNotify({
+ title: 'Unable to complete request',
+ text: response.data.error_message,
+ type: 'error'
+ });
+
+ }
+ }
+ function cantLoadInitialData(response) {
+ new PNotify({
+ title: 'Unable to complete request',
+ type: 'error'
+ });
+ }
+ }
+
+ url = "/docker/getContainerList";
+
+ var data = {page: 1};
+
+ var config = {
+ headers : {
+ 'X-CSRFToken': getCookie('csrftoken')
+ }
+ };
+
+ $http.post(url, data,config).then(ListInitialData, cantLoadInitialData);
+
+
+ function ListInitialData(response) {
+ console.log(response);
+
+ if (response.data.listContainerStatus === 1) {
+
+ var finalData = JSON.parse(response.data.data);
+ $scope.ContainerList = finalData;
+ console.log($scope.ContainerList);
+ $("#listFail").hide();
+ }
+ else
+ {
+ $("#listFail").fadeIn();
+ $scope.errorMessage = response.data.error_message;
+
+ }
+ }
+ function cantLoadInitialData(response) {
+ console.log("not good");
+ }
+
+
+ $scope.getFurtherContainersFromDB = function(pageNumber) {
+
+ var config = {
+ headers : {
+ 'X-CSRFToken': getCookie('csrftoken')
+ }
+ };
+
+ var data = {page: pageNumber};
+
+
+ dataurl = "/docker/getContainerList";
+
+ $http.post(dataurl, data,config).then(ListInitialData, cantLoadInitialData);
+
+
+ function ListInitialData(response) {
+ if (response.data.listContainerStatus ===1) {
+
+ var finalData = JSON.parse(response.data.data);
+ $scope.ContainerList = finalData;
+ $("#listFail").hide();
+ }
+ else
+ {
+ $("#listFail").fadeIn();
+ $scope.errorMessage = response.data.error_message;
+ console.log(response.data);
+
+ }
+ }
+ function cantLoadInitialData(response) {
+ console.log("not good");
+ }
+
+
+
+ };
+});
+
+/* Java script code for containerr home page */
+
+app.controller('viewContainer', function($scope,$http) {
+ $scope.cName = "";
+ $scope.status = "";
+ $scope.savingSettings = false;
+ $scope.loadingTop = false;
+
+ $scope.recreate = function() {
+ (new PNotify({
+ title: 'Confirmation Needed',
+ text: 'Are you sure?',
+ icon: 'fa fa-question-circle',
+ hide: false,
+ confirm: {
+ confirm: true
+ },
+ buttons: {
+ closer: false,
+ sticker: false
+ },
+ history: {
+ history: false
+ }
+ })).get().on('pnotify.confirm', function() {
+ $('#infoLoading').show();
+
+ url = "/docker/recreateContainer";
+ var data = {name: $scope.cName};
+ var config = {
+ headers : {
+ 'X-CSRFToken': getCookie('csrftoken')
+ }
+ };
+
+ $http.post(url, data,config).then(ListInitialData, cantLoadInitialData);
+ function ListInitialData(response) {
+ if (response.data.recreateContainerStatus === 1) {
+ new PNotify({
+ title: 'Action completed!',
+ text: 'Redirecting...',
+ type: 'success'
+ });
+ location.reload();
+ }
+ else
+ {
+ new PNotify({
+ title: 'Unable to complete request',
+ text: response.data.error_message,
+ type: 'error'
+ });
+
+ }
+ $('#infoLoading').hide();
+ }
+ function cantLoadInitialData(response) {
+ PNotify.error({
+ title: 'Unable to complete request',
+ text: "Problem in connecting to server"
+ });
+ $('#actionLoading').hide();
+ }
+ })
+ }
+
+ $scope.addEnvField = function() {
+ var countEnv = Object.keys($scope.envList).length;
+ $scope.envList[countEnv+1] = {'name':'', 'value':''};
+ }
+
+ $scope.showTop = function(){
+ $scope.topHead = [];
+ $scope.topProcesses = [];
+ $scope.loadingTop = true;
+ $("#processes").modal("show");
+
+ url = "/docker/getContainerTop";
+ var data = {name: $scope.cName};
+ var config = {
+ headers : {
+ 'X-CSRFToken': getCookie('csrftoken')
+ }
+ };
+
+ $http.post(url, data,config).then(ListInitialData, cantLoadInitialData);
+ function ListInitialData(response) {
+ if (response.data.containerTopStatus === 1) {
+ $scope.topHead = response.data.processes.Titles;
+ $scope.topProcesses = response.data.processes.Processes;
+ }
+ else
+ {
+ new PNotify({
+ title: 'Unable to complete request',
+ text: response.data.error_message,
+ type: 'error'
+ });
+
+ }
+ $scope.loadingTop = false;
+ }
+ function cantLoadInitialData(response) {
+ PNotify.error({
+ title: 'Unable to complete request',
+ text: "Problem in connecting to server"
+ });
+ $scope.loadingTop = false;
+ }
+
+ }
+
+ $scope.cRemove = function(){
+ (new PNotify({
+ title: 'Confirmation Needed',
+ text: 'Are you sure?',
+ icon: 'fa fa-question-circle',
+ hide: false,
+ confirm: {
+ confirm: true
+ },
+ buttons: {
+ closer: false,
+ sticker: false
+ },
+ history: {
+ history: false
+ }
+ })).get().on('pnotify.confirm', function() {
+ $('#actionLoading').show();
+
+ url = "/docker/delContainer";
+ var data = {name: $scope.cName, unlisted: false};
+ var config = {
+ headers : {
+ 'X-CSRFToken': getCookie('csrftoken')
+ }
+ };
+
+ $http.post(url, data,config).then(ListInitialData, cantLoadInitialData);
+ function ListInitialData(response) {
+ if (response.data.delContainerStatus === 1) {
+ new PNotify({
+ title: 'Container deleted!',
+ text: 'Redirecting...',
+ type: 'success'
+ });
+ window.location.href = '/docker/listContainers';
+ }
+ else
+ {
+ new PNotify({
+ title: 'Unable to complete request',
+ text: response.data.error_message,
+ type: 'error'
+ });
+ }
+ $('#actionLoading').hide();
+ }
+ function cantLoadInitialData(response) {
+ PNotify.error({
+ title: 'Unable to complete request',
+ text: "Problem in connecting to server"
+ });
+ $('#actionLoading').hide();
+ }
+ })
+ }
+
+ $scope.refreshStatus = function(){
+ url = "/docker/getContainerStatus";
+ var data = {name: $scope.cName};
+ var config = {
+ headers : {
+ 'X-CSRFToken': getCookie('csrftoken')
+ }
+ };
+
+ $http.post(url, data,config).then(ListInitialData, cantLoadInitialData);
+ function ListInitialData(response) {
+ if (response.data.containerStatus === 1) {
+ console.log(response.data.status);
+ $scope.status = response.data.status;
+ }
+ else
+ {
+ new PNotify({
+ title: 'Unable to complete request',
+ text: response.data.error_message,
+ type: 'error'
+ });
+
+ }
+ }
+ function cantLoadInitialData(response) {
+ PNotify.error({
+ title: 'Unable to complete request',
+ text: "Problem in connecting to server"
+ });
+ }
+
+ }
+
+ $scope.saveSettings = function(){
+ $('#containerSettingLoading').show();
+ url = "/docker/saveContainerSettings";
+ $scope.savingSettings = true;
+
+ var data = {
+ name: $scope.cName,
+ memory:$scope.memory,
+ startOnReboot: $scope.startOnReboot,
+ envConfirmation: $scope.envConfirmation,
+ envList: $scope.envList
+ };
+
+ console.log(data)
+ var config = {
+ headers : {
+ 'X-CSRFToken': getCookie('csrftoken')
+ }
+ };
+
+ $http.post(url, data,config).then(ListInitialData, cantLoadInitialData);
+ function ListInitialData(response) {
+ if (response.data.saveSettingsStatus === 1) {
+ if ($scope.envConfirmation){
+ new PNotify({
+ title: 'Done. Redirecting...',
+ type: 'success'
+ });
+ location.reload();
+ }
+ else{
+ new PNotify({
+ title: 'Settings Saved',
+ type: 'success'
+ });
+ }
+ }
+ else
+ {
+ new PNotify({
+ title: 'Unable to complete request',
+ text: response.data.error_message,
+ type: 'error'
+ });
+
+ }
+ $('#containerSettingLoading').hide();
+ $scope.savingSettings = false;
+ }
+ function cantLoadInitialData(response) {
+ new PNotify({
+ title: 'Unable to complete request',
+ text: "Problem in connecting to server",
+ type: 'error'
+ });
+ $('#containerSettingLoading').hide();
+ $scope.savingSettings = false;
+ }
+
+ if ($scope.startOnReboot === true){
+ $scope.rPolicy="Yes";
+ }
+ else{
+ $scope.rPolicy="No";
+ }
+
+ }
+
+ $scope.cAction = function(action){
+ $('#actionLoading').show();
+ console.log($scope.cName)
+ url = "/docker/doContainerAction";
+ var data = {name: $scope.cName, action: action};
+ var config = {
+ headers : {
+ 'X-CSRFToken': getCookie('csrftoken')
+ }
+ };
+
+ $http.post(url, data,config).then(ListInitialData, cantLoadInitialData);
+
+
+ function ListInitialData(response) {
+ console.log(response);
+
+ if (response.data.containerActionStatus === 1) {
+ new PNotify({
+ title: 'Success!',
+ text: 'Action completed',
+ type: 'success'
+ });
+ $scope.status = response.data.status;
+ $scope.refreshStatus()
+ }
+ else
+ {
+ new PNotify({
+ title: 'Unable to complete request',
+ text: response.data.error_message,
+ type: 'error'
+ });
+
+ }
+ $('#actionLoading').hide();
+ }
+ function cantLoadInitialData(response) {
+ PNotify.error({
+ title: 'Unable to complete request',
+ text: "Problem in connecting to server"
+ });
+ $('#actionLoading').hide();
+ }
+
+ }
+
+ $scope.loadLogs = function(name){
+ $scope.logs = "Loading...";
+
+ url = "/docker/getContainerLogs";
+
+ var data = {name: name};
+
+ var config = {
+ headers : {
+ 'X-CSRFToken': getCookie('csrftoken')
+ }
+ };
+
+ $http.post(url, data,config).then(ListInitialData, cantLoadInitialData);
+
+
+ function ListInitialData(response) {
+ console.log(response);
+
+ if (response.data.containerLogStatus === 1) {
+ $scope.logs = response.data.containerLog;
+ }
+ else
+ {
+ $scope.logs = response.data.error_message;
+
+ }
+ }
+ function cantLoadInitialData(response) {
+ console.log("not good");
+ $scope.logs = "Error loading log";
+ }
+ }
+
+});
+
+
+/* Java script code for docker image management */
+app.controller('manageImages', function($scope,$http) {
+ $scope.tagList = [];
+ $scope.showingSearch = false;
+ $("#searchResult").hide();
+
+ $scope.pullImage = function(image, tag){
+ function ListInitialDatas(response) {
+ if (response.data.installImageStatus === 1)
+ {
+ new PNotify({
+ title: 'Image pulled successfully',
+ text: 'Reloading...',
+ type: 'success'
+ });
+ location.reload()
+ }
+ else{
+ new PNotify({
+ title: 'Failed to complete request',
+ text: response.data.error_message,
+ type: 'error'
+ });
+ }
+
+ $('#imageLoading').hide();
+
+ }
+ function cantLoadInitialDatas(response) {
+ $('#imageLoading').hide();
+ new PNotify({
+ title: 'Failed to complete request',
+ type: 'error'
+ });
+ }
+ if (image && tag){
+ $('#imageLoading').show();
+
+ url = "/docker/installImage";
+ var data = {
+ image: image,
+ tag: tag
+ };
+ var config = {
+ headers : {
+ 'X-CSRFToken': getCookie('csrftoken')
+ }
+ };
+
+ $http.post(url, data,config).then(ListInitialDatas, cantLoadInitialDatas);
+
+ }
+ else {
+ new PNotify({
+ title: 'Unable to complete request',
+ text: 'Please select a tag',
+ type: 'info'
+ });
+ }
+
+ }
+
+ $scope.searchImages = function(){
+ console.log($scope.searchString);
+ if (!$scope.searchString){
+ $("#searchResult").hide();
+ }
+ else {
+ $("#searchResult").show();
+ }
+ clearTimeout(delayTimer);
+ delayTimer = setTimeout(function() {
+ $('#imageLoading').show();
+
+ url = "/docker/searchImage";
+ var data = {
+ string: $scope.searchString
+ };
+ var config = {
+ headers : {
+ 'X-CSRFToken': getCookie('csrftoken')
+ }
+ };
+
+ $http.post(url, data,config).then(ListInitialDatas, cantLoadInitialDatas);
+
+ function ListInitialDatas(response) {
+ if (response.data.searchImageStatus === 1)
+ {
+ $scope.images = response.data.matches;
+ console.log($scope.images)
+ }
+ else{
+ new PNotify({
+ title: 'Failed to complete request',
+ text: response.data.error,
+ type: 'error'
+ });
+ }
+
+ $('#imageLoading').hide();
+
+ }
+ function cantLoadInitialDatas(response) {
+ $('#imageLoading').hide();
+ new PNotify({
+ title: 'Failed to complete request',
+ type: 'error'
+ });
+ }
+ }, 500);
+ }
+
+ function populateTagList(image, page){
+ $('imageLoading').show();
+ url = "/docker/getTags"
+ var data = {
+ image: image,
+ page: page+1
+ };
+
+ var config = {
+ headers : {
+ 'X-CSRFToken': getCookie('csrftoken')
+ }
+ };
+ $http.post(url, data,config).then(ListInitialData, cantLoadInitialData);
+
+
+ function ListInitialData(response) {
+
+ if (response.data.getTagsStatus === 1) {
+ $scope.tagList[image].splice(-1,1);
+ $scope.tagList[image] = $scope.tagList[image].concat(response.data.list);
+
+ if (response.data.next != null){
+ $scope.tagList[image].push("Load more");
+ }
+ }
+ else
+ {
+ new PNotify({
+ title: 'Unable to complete request',
+ text: response.data.error_message,
+ type: 'error'
+ });
+ }
+ $('#imageLoading').hide();
+ }
+ function cantLoadInitialData(response) {
+ new PNotify({
+ title: 'Unable to complete request',
+ text: response.data.error_message,
+ type: 'error'
+ });
+ $('#imageLoading').hide();
+ }
+ }
+
+ $scope.runContainer = function(image){
+ $("#errorMessage").hide();
+ if ($scope.imageTag[image] !== undefined) {
+ $("#imageList").css("pointer-events","none");
+ }
+ else {
+ $("#errorMessage").show();
+ $scope.errorMessage = "Please select a tag";
+ }
+ }
+
+ $scope.loadTags = function(event){
+ var pagesloaded = $(event.target).data('pageloaded');
+ var image = event.target.id;
+
+ if (!pagesloaded) {
+ $scope.tagList[image] = ['Loading...'];
+ $(event.target).data('pageloaded',1);
+
+ populateTagList(image, pagesloaded);
+// $("#"+image+" option:selected").prop("selected", false);
+ }
+ }
+
+ $scope.selectTag = function(){
+ var image = event.target.id;
+ var selectedTag = $('#'+image).find(":selected").text();
+
+ if (selectedTag == 'Load more') {
+ var pagesloaded = $(event.target).data('pageloaded');
+ $(event.target).data('pageloaded', pagesloaded+1);
+
+ populateTagList(image, pagesloaded);
+ }
+ }
+
+ $scope.getHistory = function(counter){
+ $('#imageLoading').show();
+ var name = $("#"+counter).val()
+
+ url = "/docker/getImageHistory";
+
+ var data = {name: name};
+
+ var config = {
+ headers : {
+ 'X-CSRFToken': getCookie('csrftoken')
+ }
+ };
+
+ $http.post(url, data,config).then(ListInitialData, cantLoadInitialData);
+
+
+ function ListInitialData(response) {
+ console.log(response);
+
+ if (response.data.imageHistoryStatus === 1) {
+ $('#history').modal('show');
+ $scope.historyList = response.data.history;
+ }
+ else
+ {
+ new PNotify({
+ title: 'Unable to complete request',
+ text: response.data.error_message,
+ type: 'error'
+ });
+ }
+ $('#imageLoading').hide();
+ }
+ function cantLoadInitialData(response) {
+ new PNotify({
+ title: 'Unable to complete request',
+ text: response.data.error_message,
+ type: 'error'
+ });
+ $('#imageLoading').hide();
+ }
+ }
+
+ $scope.rmImage = function(counter){
+
+ (new PNotify({
+ title: 'Confirmation Needed',
+ text: 'Are you sure?',
+ icon: 'fa fa-question-circle',
+ hide: false,
+ confirm: {
+ confirm: true
+ },
+ buttons: {
+ closer: false,
+ sticker: false
+ },
+ history: {
+ history: false
+ }
+ })).get().on('pnotify.confirm', function() {
+ $('#imageLoading').show();
+
+ if (counter == '0') {
+ var name = 0;
+ }
+ else {
+ var name = $("#"+counter).val()
+ }
+
+ url = "/docker/removeImage";
+
+ var data = {name: name};
+
+ var config = {
+ headers : {
+ 'X-CSRFToken': getCookie('csrftoken')
+ }
+ };
+
+ $http.post(url, data,config).then(ListInitialData, cantLoadInitialData);
+
+
+ function ListInitialData(response) {
+ console.log(response);
+
+ if (response.data.removeImageStatus === 1) {
+ new PNotify({
+ title: 'Image(s) removed',
+ type: 'success'
+ });
+ window.location.href = "/docker/manageImages";
+ }
+ else
+ {
+ new PNotify({
+ title: 'Unable to complete request',
+ text: response.data.error_message,
+ type: 'error'
+ });
+ }
+ $('#imageLoading').hide();
+ }
+ function cantLoadInitialData(response) {
+ new PNotify({
+ title: 'Unable to complete request',
+ text: response.data.error_message,
+ type: 'error'
+ });
+ $('#imageLoading').hide();
+ }
+
+ })
+ }
+});
\ No newline at end of file
diff --git a/dockerManager/templates/dockerManager/images.html b/dockerManager/templates/dockerManager/images.html
new file mode 100644
index 000000000..480dd7ae5
--- /dev/null
+++ b/dockerManager/templates/dockerManager/images.html
@@ -0,0 +1,64 @@
+{% extends "baseTemplate/index.html" %}
+{% load i18n %}
+{% block title %}{% trans "Docker Manage Images - CyberPanel" %}{% endblock %}
+{% block content %}
+
+{% load static %}
+{% get_current_language as LANGUAGE_CODE %}
+
+
+
+
+
+
+
{% trans "Create new container" %}
+ Manage Images
+
+
+
+
+
+
+ {% trans "Installed Images" %}
+ {{ test }}
+
+
+
+
+
+
+
+ Name (Installed)
+ Tags
+ Action
+
+
+
+
+ {% for name, image in images.items %}
+
+ {{image.name}}
+
+
+ {% for tag in image.tags%}
+ {{tag}}
+ {% endfor %}
+
+
+
+ {% trans "Create" %}
+
+
+
+ {% endfor %}
+
+
+
+
+
+
+
+
+
+
+{% endblock %}
\ No newline at end of file
diff --git a/dockerManager/templates/dockerManager/index.html b/dockerManager/templates/dockerManager/index.html
new file mode 100644
index 000000000..f108fc189
--- /dev/null
+++ b/dockerManager/templates/dockerManager/index.html
@@ -0,0 +1,67 @@
+{% extends "baseTemplate/index.html" %}
+{% load i18n %}
+{% block title %}{% trans "Docker Container Management - CyberPanel" %}{% endblock %}
+{% block content %}
+
+{% load static %}
+{% get_current_language as LANGUAGE_CODE %}
+
+
+
+
+
+
{% trans "Docker Container Management" %}
+
+
+
+
+
+
+
+ {% trans "Available Functions" %}
+
+
+
+
+
+
+
+
+
+
+
+{% endblock %}
\ No newline at end of file
diff --git a/dockerManager/templates/dockerManager/install.html b/dockerManager/templates/dockerManager/install.html
new file mode 100644
index 000000000..a3de1b5c9
--- /dev/null
+++ b/dockerManager/templates/dockerManager/install.html
@@ -0,0 +1,50 @@
+{% extends "baseTemplate/index.html" %}
+{% load i18n %}
+{% block title %}{% trans "Install Docker - CyberPanel" %}{% endblock %}
+{% block content %}
+
+{% load static %}
+{% get_current_language as LANGUAGE_CODE %}
+
+
+
+
+
{% trans "Install Docker" %}
+
+
+
+
+
+
+ {% trans "Install Docker" %}
+
+
+
+ {% if conErr == 1%}
+
+ {% if status == 1 %}
+ {% trans "Unable to connect to docker daemon, please try restarting docker from service page" %}
+ {% else %}
+ {% trans "You do not have sufficient permissions to access this page" %}
+ {% endif %}
+
+ {% else %}
+
{% trans "Docker is currently not installed on this server. To manage containers, you must first install it." %}
+
+ {% if status == 1 %}
+
Install Docker
+ {% else %}
+ {% trans "You do not have permissions to install Docker. Please contact your system administrator" %}
+ {% endif %}
+ {% endif %}
+
+
+
+
+
+
+
+
+
+
+{% endblock %}
\ No newline at end of file
diff --git a/dockerManager/templates/dockerManager/listContainers.html b/dockerManager/templates/dockerManager/listContainers.html
new file mode 100644
index 000000000..b49a5de34
--- /dev/null
+++ b/dockerManager/templates/dockerManager/listContainers.html
@@ -0,0 +1,177 @@
+{% extends "baseTemplate/index.html" %}
+{% load i18n %}
+{% block title %}{% trans "Containers List - CyberPanel" %}{% endblock %}
+{% block content %}
+
+{% load static %}
+{% get_current_language as LANGUAGE_CODE %}
+
+
+
+
+
+
+
{% trans "List Containers" %}
+ Create
+
+
{% trans "Manage containers on server" %}
+
+
+
+
+
+ {% trans "Containers" %}
+
+
+
+
+
+
+ Name
+ Launch
+ Owner
+ Image
+ Tag
+ Actions
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
{% trans "Error message:" %} {$ errorMessage $}
+
+
+
+
+ {% if showUnlistedContainer %}
+
+ {% trans "Unlisted Containers" %}
+
+
+
+
+
+ Name
+ Status
+ Actions
+
+
+
+
+ {% for container in unlistedContainers %}
+
+ {{container.name}}
+ {{container.status}}
+
+
+
+
+
+
+ {% endfor %}
+
+
+
+
+ {% endif %}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+{% endblock %}
\ No newline at end of file
diff --git a/dockerManager/templates/dockerManager/manageImages.html b/dockerManager/templates/dockerManager/manageImages.html
new file mode 100644
index 000000000..4e219abdd
--- /dev/null
+++ b/dockerManager/templates/dockerManager/manageImages.html
@@ -0,0 +1,151 @@
+{% extends "baseTemplate/index.html" %}
+{% load i18n %}
+{% block title %}{% trans "Docker Manage Images - CyberPanel" %}{% endblock %}
+{% block content %}
+
+{% load static %}
+{% get_current_language as LANGUAGE_CODE %}
+
+
+
+
+
+
+
{% trans "Manage Images" %}
+ Create
+
+
{% trans "On this page you can manage docker images." %}
+
+
+
+
+
+
+
+
+
+
+
+
+ ID
+ CreatedBy
+ Created
+ Comment
+ Size
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {% trans "Images" %}
+ {% trans "Images" %}
+ Prune
+
+
+
+
+
Search Image
+
+
+
+
+
+
+
+
+
+
+
+
+ Name (search)
+ Tags
+ Action
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {% trans "Pull" %}
+
+
+
+
+
+
+
+
+
+ Name (Installed)
+ Tags
+ Action
+
+
+
+
+
+ {% for name, image in images.items %}
+
+
+ {{image.name}}
+
+
+ {% for tag in image.tags%}
+ {{tag}}
+ {% endfor %}
+
+
+
+
+
+
+
+
+ {% endfor %}
+
+
+
+
+
+
+
+
+
+
+{% endblock %}
\ No newline at end of file
diff --git a/dockerManager/templates/dockerManager/runContainer.html b/dockerManager/templates/dockerManager/runContainer.html
new file mode 100644
index 000000000..e89074fd6
--- /dev/null
+++ b/dockerManager/templates/dockerManager/runContainer.html
@@ -0,0 +1,170 @@
+{% extends "baseTemplate/index.html" %}
+{% load i18n %}
+{% block title %}{% trans "Run new container - CyberPanel" %}{% endblock %}
+{% block content %}
+
+{% load static %}
+{% get_current_language as LANGUAGE_CODE %}
+
+
+
+
+
{% trans "Run Container" %}
+
{% trans "Modify parameters for your new container" %}
+
+
+
+
+
+
+ {% trans "Container Details" %}
+
+
+
+
+
+
+
+
+
+
+{% endblock %}
\ No newline at end of file
diff --git a/dockerManager/templates/dockerManager/viewContainer.html b/dockerManager/templates/dockerManager/viewContainer.html
new file mode 100644
index 000000000..3baa62e11
--- /dev/null
+++ b/dockerManager/templates/dockerManager/viewContainer.html
@@ -0,0 +1,303 @@
+{% extends "baseTemplate/index.html" %}
+{% load i18n %}
+{% block title %}{% trans "Container Home - CyberPanel" %}{% endblock %}
+{% block content %}
+
+{% load static %}
+{% get_current_language as LANGUAGE_CODE %}
+
+
+
+
+
+
+
{% trans "Manage Container" %}
+
{% trans "Currently managing: " %} {{ name }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {% trans "Memory Usage" %}
+
+
+
+
+
{{ memoryUsage | floatformat:"2" }}%
+
+
+
+
+
+ {% trans "CPU Usage" %}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {% trans "Container ID" %}: {{cid}}
+
+ {% trans "Image" %}: {{image}}
+
+
+
+
+ {% if ports %}
+ {% trans "Ports" %}:
+ {% for iport, eport in ports.items %}
+ {{iport}} {% trans "to" %} {{eport}}
+ {% endfor %}
+ {% endif %}
+
+
+
+
Settings
+
Recreate
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Main Actions
+
+
+
Status:
+
+
+
Start
+
Restart
+
Stop
+
Remove
+
+
+
+
+
+
+
+
+
+
Other Actions
+
Restart on system reboot:
+
Export file
+
View Process
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {$ item $}
+
+
+
+
+
+ {$ item $}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+{% endblock %}
\ No newline at end of file
diff --git a/dockerManager/tests.py b/dockerManager/tests.py
new file mode 100644
index 000000000..5982e6bcd
--- /dev/null
+++ b/dockerManager/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/dockerManager/urls.py b/dockerManager/urls.py
new file mode 100644
index 000000000..0bb5ca064
--- /dev/null
+++ b/dockerManager/urls.py
@@ -0,0 +1,29 @@
+from django.conf.urls import url
+import views
+
+urlpatterns = [
+ url(r'^$', views.loadDockerHome, name='dockerHome'),
+# url(r'^images', views.loadImages, name='loadImages'),
+ url(r'^getTags', views.getTags, name='getTags'),
+ url(r'^runContainer', views.runContainer, name='runContainer'),
+ url(r'^submitContainerCreation', views.submitContainerCreation, name='submitContainerCreation'),
+ url(r'^listContainers', views.listContainers, name='listContainers'),
+ url(r'^getContainerList', views.getContainerList, name='getContainerList'),
+ url(r'^getContainerLogs', views.getContainerLogs, name='getContainerLogs'),
+ url(r'^installImage', views.installImage, name='installImage'),
+ url(r'^delContainer', views.delContainer, name='delContainer'),
+ url(r'^doContainerAction', views.doContainerAction, name='doContainerAction'),
+ url(r'^getContainerStatus', views.getContainerStatus, name='getContainerStatus'),
+ url(r'^exportContainer', views.exportContainer, name='exportContainer'),
+ url(r'^saveContainerSettings', views.saveContainerSettings, name='saveContainerSettings'),
+ url(r'^getContainerTop', views.getContainerTop, name='getContainerTop'),
+ url(r'^assignContainer', views.assignContainer, name='assignContainer'),
+ url(r'^searchImage', views.searchImage, name='searchImage'),
+ url(r'^manageImages', views.manageImages, name='manageImages'),
+ url(r'^getImageHistory', views.getImageHistory, name='getImageHistory'),
+ url(r'^removeImage', views.removeImage, name='removeImage'),
+ url(r'^recreateContainer', views.recreateContainer, name='recreateContainer'),
+ url(r'^installDocker', views.installDocker, name='installDocker'),
+ url(r'^images', views.images, name='containerImage'),
+ url(r'^view/(?P
(.*))$', views.viewContainer, name='viewContainer'),
+]
\ No newline at end of file
diff --git a/dockerManager/views.py b/dockerManager/views.py
new file mode 100644
index 000000000..d68f9c954
--- /dev/null
+++ b/dockerManager/views.py
@@ -0,0 +1,362 @@
+ # -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.shortcuts import render,redirect
+from loginSystem.models import Administrator
+from loginSystem.views import loadLoginPage
+from django.http import HttpResponse
+from plogical.container import ContainerManager
+from dockerManager.pluginManager import pluginManager
+from decorators import preDockerRun
+from plogical.acl import ACLManager
+import json
+import requests
+import docker
+
+# Use default socket to connect
+client = docker.from_env()
+# Create your views here.
+
+# This function checks if user has admin permissions
+def dockerPermission(request, userID, context):
+ currentACL = ACLManager.loadedACL(userID)
+
+ if currentACL['admin'] != 1:
+ if request.method == "POST":
+ return ACLManager.loadErrorJson()
+ else:
+ return ACLManager.loadError()
+ else:
+ return None
+
+@preDockerRun
+def loadDockerHome(request):
+ try:
+ userID = request.session['userID']
+ perm = dockerPermission(request, userID, 'loadDockerHome')
+ if perm: return perm
+
+ admin = Administrator.objects.get(pk=userID)
+ return render(request,'dockerManager/index.html',{"type":admin.type})
+ except KeyError:
+ return redirect(loadLoginPage)
+
+def installDocker(request):
+ try:
+ userID = request.session['userID']
+ perm = dockerPermission(request, userID, 'loadDockerHome')
+ if perm: return perm
+ result = pluginManager.preDockerInstallation(request) # Later change to preInstallInstallation
+
+ if result != 200:
+ return result
+
+ cm = ContainerManager()
+ coreResult = cm.submitInstallDocker(userID, json.loads(request.body))
+
+ result = pluginManager.postDockerInstallation(request, coreResult)
+ if result != 200:
+ return result
+
+ return coreResult
+
+ except KeyError:
+ return redirect(loadLoginPage)
+
+@preDockerRun
+def installImage(request):
+ try:
+ userID = request.session['userID']
+ perm = dockerPermission(request, userID, 'loadDockerHome')
+ if perm: return perm
+
+ cm = ContainerManager()
+ coreResult = cm.submitInstallImage(userID, json.loads(request.body))
+
+ return coreResult
+
+ except KeyError:
+ return redirect(loadLoginPage)
+
+@preDockerRun
+def viewContainer(request, name):
+ try:
+ if not request.GET._mutable:
+ request.GET._mutable = True
+ request.GET['name'] = name
+
+ userID = request.session['userID']
+ perm = dockerPermission(request, userID, 'loadDockerHome')
+ if perm: return perm
+ cm = ContainerManager(name)
+ coreResult = cm.loadContainerHome(request, userID)
+
+ return coreResult
+
+ except KeyError:
+ return redirect(loadLoginPage)
+
+@preDockerRun
+def getTags(request):
+ try:
+ userID = request.session['userID']
+ perm = dockerPermission(request, userID, 'loadDockerHome')
+ if perm: return perm
+
+ cm = ContainerManager()
+ coreResult = cm.getTags(userID, json.loads(request.body))
+
+ return coreResult
+
+ except KeyError:
+ return redirect(loadLoginPage)
+
+@preDockerRun
+def delContainer(request):
+ try:
+ userID = request.session['userID']
+ perm = dockerPermission(request, userID, 'loadDockerHome')
+ if perm: return perm
+
+ cm = ContainerManager()
+ coreResult = cm.submitContainerDeletion(userID, json.loads(request.body))
+
+ return coreResult
+
+ except KeyError:
+ return redirect(loadLoginPage)
+
+@preDockerRun
+def recreateContainer(request):
+ try:
+ userID = request.session['userID']
+ perm = dockerPermission(request, userID, 'loadDockerHome')
+ if perm: return perm
+
+ cm = ContainerManager()
+ coreResult = cm.recreateContainer(userID, json.loads(request.body))
+
+ return coreResult
+
+ except KeyError:
+ return redirect(loadLoginPage)
+
+@preDockerRun
+def runContainer(request):
+ try:
+ userID = request.session['userID']
+ perm = dockerPermission(request, userID, 'loadDockerHome')
+ if perm: return perm
+
+ cm = ContainerManager()
+ return cm.createContainer(request, userID)
+ except KeyError:
+ return redirect(loadLoginPage)
+
+@preDockerRun
+def listContainers(request):
+ try:
+ userID = request.session['userID']
+ perm = dockerPermission(request, userID, 'loadDockerHome')
+ if perm: return perm
+
+ cm = ContainerManager()
+ return cm.listContainers(request, userID)
+ except KeyError:
+ return redirect(loadLoginPage)
+
+@preDockerRun
+def getContainerLogs(request):
+ try:
+ userID = request.session['userID']
+ perm = dockerPermission(request, userID, 'loadDockerHome')
+ if perm: return perm
+
+ cm = ContainerManager()
+ coreResult = cm.getContainerLogs(userID, json.loads(request.body))
+ return coreResult
+
+ except KeyError:
+ return redirect(loadLoginPage)
+
+@preDockerRun
+def submitContainerCreation(request):
+ try:
+ userID = request.session['userID']
+ perm = dockerPermission(request, userID, 'loadDockerHome')
+ if perm: return perm
+
+ cm = ContainerManager()
+ coreResult = cm.submitContainerCreation(userID, json.loads(request.body))
+
+ return coreResult
+
+ except KeyError:
+ return redirect(loadLoginPage)
+
+@preDockerRun
+def getContainerList(request):
+ try:
+ userID = request.session['userID']
+ perm = dockerPermission(request, userID, 'loadDockerHome')
+ if perm: return perm
+
+ cm = ContainerManager()
+ return cm.getContainerList(userID, json.loads(request.body))
+ except KeyError:
+ return redirect(loadLoginPage)
+
+@preDockerRun
+def doContainerAction(request):
+ try:
+ userID = request.session['userID']
+ perm = dockerPermission(request, userID, 'loadDockerHome')
+ if perm: return perm
+
+ cm = ContainerManager()
+ coreResult = cm.doContainerAction(userID, json.loads(request.body))
+
+ return coreResult
+ except KeyError:
+ return redirect(loadLoginPage)
+
+@preDockerRun
+def getContainerStatus(request):
+ try:
+ userID = request.session['userID']
+ perm = dockerPermission(request, userID, 'loadDockerHome')
+ if perm: return perm
+
+ cm = ContainerManager()
+ coreResult = cm.getContainerStatus(userID, json.loads(request.body))
+
+ return coreResult
+ except KeyError:
+ return redirect(loadLoginPage)
+
+@preDockerRun
+def exportContainer(request):
+ try:
+ userID = request.session['userID']
+ perm = dockerPermission(request, userID, 'loadDockerHome')
+ if perm: return perm
+
+ cm = ContainerManager()
+ coreResult = cm.exportContainer(request, userID)
+
+ return coreResult
+ except KeyError:
+ return redirect(loadLoginPage)
+
+@preDockerRun
+def saveContainerSettings(request):
+ try:
+ userID = request.session['userID']
+ perm = dockerPermission(request, userID, 'loadDockerHome')
+ if perm: return perm
+
+ cm = ContainerManager()
+ coreResult = cm.saveContainerSettings(userID, json.loads(request.body))
+
+ return coreResult
+ except KeyError:
+ return redirect(loadLoginPage)
+
+@preDockerRun
+def getContainerTop(request):
+ try:
+ userID = request.session['userID']
+ perm = dockerPermission(request, userID, 'loadDockerHome')
+ if perm: return perm
+
+ cm = ContainerManager()
+ coreResult = cm.getContainerTop(userID, json.loads(request.body))
+
+ return coreResult
+ except KeyError:
+ return redirect(loadLoginPage)
+
+@preDockerRun
+def assignContainer(request):
+ try:
+ userID = request.session['userID']
+ perm = dockerPermission(request, userID, 'loadDockerHome')
+ if perm: return perm
+
+ cm = ContainerManager()
+ coreResult = cm.assignContainer(userID, json.loads(request.body))
+
+ return coreResult
+ except KeyError:
+ return redirect(loadLoginPage)
+
+@preDockerRun
+def searchImage(request):
+ try:
+ userID = request.session['userID']
+ perm = dockerPermission(request, userID, 'loadDockerHome')
+ if perm: return perm
+
+ cm = ContainerManager()
+ coreResult = cm.searchImage(userID, json.loads(request.body))
+
+ return coreResult
+ except KeyError:
+ return redirect(loadLoginPage)
+
+@preDockerRun
+def images(request):
+ try:
+ userID = request.session['userID']
+ perm = dockerPermission(request, userID, 'images')
+ if perm: return perm
+
+
+ cm = ContainerManager()
+ coreResult = cm.images(request, userID)
+
+ return coreResult
+ except KeyError:
+ return redirect(loadLoginPage)
+
+@preDockerRun
+def manageImages(request):
+ try:
+ userID = request.session['userID']
+ perm = dockerPermission(request, userID, 'loadDockerHome')
+ if perm: return perm
+
+ cm = ContainerManager()
+ coreResult = cm.manageImages(request, userID)
+
+ return coreResult
+ except KeyError:
+ return redirect(loadLoginPage)
+
+@preDockerRun
+def getImageHistory(request):
+ try:
+ userID = request.session['userID']
+ perm = dockerPermission(request, userID, 'loadDockerHome')
+ if perm: return perm
+
+ cm = ContainerManager()
+ coreResult = cm.getImageHistory(userID, json.loads(request.body))
+
+ return coreResult
+ except KeyError:
+ return redirect(loadLoginPage)
+
+@preDockerRun
+def removeImage(request):
+ try:
+ userID = request.session['userID']
+ perm = dockerPermission(request, userID, 'loadDockerHome')
+ if perm: return perm
+
+ cm = ContainerManager()
+ coreResult = cm.removeImage(userID, json.loads(request.body))
+
+ return coreResult
+ except KeyError:
+ return redirect(loadLoginPage)
\ No newline at end of file
diff --git a/emailMarketing/migrations/0001_initial.py b/emailMarketing/migrations/0001_initial.py
new file mode 100644
index 000000000..9c0000b19
--- /dev/null
+++ b/emailMarketing/migrations/0001_initial.py
@@ -0,0 +1,87 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11 on 2019-01-07 12:43
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+ initial = True
+
+ dependencies = [
+ ('websiteFunctions', '0001_initial'),
+ ('loginSystem', '0001_initial'),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='EmailJobs',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('date', models.CharField(max_length=200)),
+ ('host', models.CharField(max_length=1000)),
+ ('totalEmails', models.IntegerField()),
+ ('sent', models.IntegerField()),
+ ('failed', models.IntegerField()),
+ ],
+ ),
+ migrations.CreateModel(
+ name='EmailLists',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('listName', models.CharField(max_length=50, unique=True)),
+ ('dateCreated', models.CharField(max_length=200)),
+ ('owner', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='websiteFunctions.Websites')),
+ ],
+ ),
+ migrations.CreateModel(
+ name='EmailMarketing',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('userName', models.CharField(max_length=50, unique=True)),
+ ],
+ ),
+ migrations.CreateModel(
+ name='EmailsInList',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('email', models.CharField(max_length=50)),
+ ('firstName', models.CharField(default='', max_length=20)),
+ ('lastName', models.CharField(default='', max_length=20)),
+ ('verificationStatus', models.CharField(max_length=100)),
+ ('dateCreated', models.CharField(max_length=200)),
+ ('owner', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='emailMarketing.EmailLists')),
+ ],
+ ),
+ migrations.CreateModel(
+ name='EmailTemplate',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('name', models.CharField(max_length=100, unique=True)),
+ ('subject', models.CharField(max_length=1000)),
+ ('fromName', models.CharField(max_length=100)),
+ ('fromEmail', models.CharField(max_length=150)),
+ ('replyTo', models.CharField(max_length=150)),
+ ('emailMessage', models.CharField(max_length=3000000)),
+ ('owner', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='loginSystem.Administrator')),
+ ],
+ ),
+ migrations.CreateModel(
+ name='SMTPHosts',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('host', models.CharField(max_length=150, unique=True)),
+ ('port', models.CharField(max_length=10)),
+ ('userName', models.CharField(max_length=50)),
+ ('password', models.CharField(max_length=50)),
+ ('owner', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='loginSystem.Administrator')),
+ ],
+ ),
+ migrations.AddField(
+ model_name='emailjobs',
+ name='owner',
+ field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='emailMarketing.EmailTemplate'),
+ ),
+ ]
diff --git a/emailPremium/migrations/0001_initial.py b/emailPremium/migrations/0001_initial.py
new file mode 100644
index 000000000..343d614e1
--- /dev/null
+++ b/emailPremium/migrations/0001_initial.py
@@ -0,0 +1,50 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11 on 2019-01-07 12:43
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+ initial = True
+
+ dependencies = [
+ ('mailServer', '0001_initial'),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='DomainLimits',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('limitStatus', models.IntegerField(default=0)),
+ ('monthlyLimit', models.IntegerField(default=10000)),
+ ('monthlyUsed', models.IntegerField(default=0)),
+ ('domain', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='mailServer.Domains')),
+ ],
+ ),
+ migrations.CreateModel(
+ name='EmailLimits',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('limitStatus', models.IntegerField(default=0)),
+ ('monthlyLimits', models.IntegerField(default=2000)),
+ ('monthlyUsed', models.IntegerField(default=0)),
+ ('hourlyLimit', models.IntegerField(default=50)),
+ ('hourlyUsed', models.IntegerField(default=0)),
+ ('emailLogs', models.IntegerField(default=0)),
+ ('email', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='mailServer.EUsers')),
+ ],
+ ),
+ migrations.CreateModel(
+ name='EmailLogs',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('destination', models.CharField(max_length=200)),
+ ('timeStamp', models.CharField(max_length=200)),
+ ('email', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='mailServer.EUsers')),
+ ],
+ ),
+ ]
diff --git a/firewall/migrations/0001_initial.py b/firewall/migrations/0001_initial.py
new file mode 100644
index 000000000..d3899c19d
--- /dev/null
+++ b/firewall/migrations/0001_initial.py
@@ -0,0 +1,26 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11 on 2019-01-07 12:43
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ initial = True
+
+ dependencies = [
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='FirewallRules',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('name', models.CharField(max_length=32, unique=True)),
+ ('proto', models.CharField(max_length=10)),
+ ('port', models.CharField(max_length=25)),
+ ('ipAddress', models.CharField(default=b'0.0.0.0/0', max_length=30)),
+ ],
+ ),
+ ]
diff --git a/ftp/migrations/0001_initial.py b/ftp/migrations/0001_initial.py
new file mode 100644
index 000000000..a611f1f23
--- /dev/null
+++ b/ftp/migrations/0001_initial.py
@@ -0,0 +1,39 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11 on 2019-01-07 12:43
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+ initial = True
+
+ dependencies = [
+ ('websiteFunctions', '0001_initial'),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='Users',
+ fields=[
+ ('id', models.AutoField(db_column=b'ID', primary_key=True, serialize=False)),
+ ('user', models.CharField(db_column=b'User', max_length=32, unique=True)),
+ ('password', models.CharField(db_column=b'Password', max_length=64)),
+ ('uid', models.IntegerField(db_column=b'Uid')),
+ ('gid', models.IntegerField(db_column=b'Gid')),
+ ('dir', models.CharField(db_column=b'Dir', max_length=255)),
+ ('quotasize', models.IntegerField(db_column=b'QuotaSize')),
+ ('status', models.CharField(db_column=b'Status', max_length=1)),
+ ('ulbandwidth', models.IntegerField(db_column=b'ULBandwidth')),
+ ('dlbandwidth', models.IntegerField(db_column=b'DLBandwidth')),
+ ('date', models.DateField(db_column=b'Date')),
+ ('lastmodif', models.CharField(db_column=b'LastModif', max_length=255)),
+ ('domain', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='websiteFunctions.Websites')),
+ ],
+ options={
+ 'db_table': 'users',
+ },
+ ),
+ ]
diff --git a/loginSystem/migrations/0001_initial.py b/loginSystem/migrations/0001_initial.py
new file mode 100644
index 000000000..e03153842
--- /dev/null
+++ b/loginSystem/migrations/0001_initial.py
@@ -0,0 +1,76 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11 on 2019-01-07 12:43
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+ initial = True
+
+ dependencies = [
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='ACL',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('name', models.CharField(max_length=50, unique=True)),
+ ('adminStatus', models.IntegerField(default=0)),
+ ('versionManagement', models.IntegerField(default=0)),
+ ('createNewUser', models.IntegerField(default=0)),
+ ('deleteUser', models.IntegerField(default=0)),
+ ('resellerCenter', models.IntegerField(default=0)),
+ ('changeUserACL', models.IntegerField(default=0)),
+ ('createWebsite', models.IntegerField(default=0)),
+ ('modifyWebsite', models.IntegerField(default=0)),
+ ('suspendWebsite', models.IntegerField(default=0)),
+ ('deleteWebsite', models.IntegerField(default=0)),
+ ('createPackage', models.IntegerField(default=0)),
+ ('deletePackage', models.IntegerField(default=0)),
+ ('modifyPackage', models.IntegerField(default=0)),
+ ('createDatabase', models.IntegerField(default=1)),
+ ('deleteDatabase', models.IntegerField(default=1)),
+ ('listDatabases', models.IntegerField(default=1)),
+ ('createNameServer', models.IntegerField(default=0)),
+ ('createDNSZone', models.IntegerField(default=1)),
+ ('deleteZone', models.IntegerField(default=1)),
+ ('addDeleteRecords', models.IntegerField(default=1)),
+ ('createEmail', models.IntegerField(default=1)),
+ ('deleteEmail', models.IntegerField(default=1)),
+ ('emailForwarding', models.IntegerField(default=1)),
+ ('changeEmailPassword', models.IntegerField(default=1)),
+ ('dkimManager', models.IntegerField(default=1)),
+ ('createFTPAccount', models.IntegerField(default=1)),
+ ('deleteFTPAccount', models.IntegerField(default=1)),
+ ('listFTPAccounts', models.IntegerField(default=1)),
+ ('createBackup', models.IntegerField(default=1)),
+ ('restoreBackup', models.IntegerField(default=0)),
+ ('addDeleteDestinations', models.IntegerField(default=0)),
+ ('scheDuleBackups', models.IntegerField(default=0)),
+ ('remoteBackups', models.IntegerField(default=0)),
+ ('manageSSL', models.IntegerField(default=1)),
+ ('hostnameSSL', models.IntegerField(default=0)),
+ ('mailServerSSL', models.IntegerField(default=0)),
+ ],
+ ),
+ migrations.CreateModel(
+ name='Administrator',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('userName', models.CharField(max_length=50, unique=True)),
+ ('password', models.CharField(max_length=200)),
+ ('firstName', models.CharField(default='None', max_length=20)),
+ ('lastName', models.CharField(default='None', max_length=20)),
+ ('email', models.CharField(max_length=50)),
+ ('type', models.IntegerField()),
+ ('owner', models.IntegerField(default=1)),
+ ('token', models.CharField(default='None', max_length=500)),
+ ('initWebsitesLimit', models.IntegerField(default=0)),
+ ('acl', models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, to='loginSystem.ACL')),
+ ],
+ ),
+ ]
diff --git a/mailServer/migrations/0001_initial.py b/mailServer/migrations/0001_initial.py
new file mode 100644
index 000000000..1fce24d41
--- /dev/null
+++ b/mailServer/migrations/0001_initial.py
@@ -0,0 +1,61 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11 on 2019-01-07 12:43
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+ initial = True
+
+ dependencies = [
+ ('websiteFunctions', '0001_initial'),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='Domains',
+ fields=[
+ ('domain', models.CharField(max_length=50, primary_key=True, serialize=False)),
+ ('domainOwner', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='websiteFunctions.Websites')),
+ ],
+ options={
+ 'db_table': 'e_domains',
+ },
+ ),
+ migrations.CreateModel(
+ name='EUsers',
+ fields=[
+ ('email', models.CharField(max_length=80, primary_key=True, serialize=False)),
+ ('password', models.CharField(max_length=20)),
+ ('emailOwner', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='mailServer.Domains')),
+ ],
+ options={
+ 'db_table': 'e_users',
+ },
+ ),
+ migrations.CreateModel(
+ name='Forwardings',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('source', models.CharField(max_length=80)),
+ ('destination', models.TextField()),
+ ],
+ options={
+ 'db_table': 'e_forwardings',
+ },
+ ),
+ migrations.CreateModel(
+ name='Transport',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('domain', models.CharField(max_length=128, unique=True)),
+ ('transport', models.CharField(max_length=128)),
+ ],
+ options={
+ 'db_table': 'e_transport',
+ },
+ ),
+ ]
diff --git a/managePHP/migrations/0001_initial.py b/managePHP/migrations/0001_initial.py
new file mode 100644
index 000000000..c66f5ae7a
--- /dev/null
+++ b/managePHP/migrations/0001_initial.py
@@ -0,0 +1,38 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11 on 2019-01-07 12:43
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+ initial = True
+
+ dependencies = [
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='installedPackages',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('extensionName', models.CharField(max_length=50)),
+ ('description', models.CharField(max_length=255)),
+ ('status', models.IntegerField()),
+ ],
+ ),
+ migrations.CreateModel(
+ name='PHP',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('phpVers', models.CharField(max_length=5, unique=True)),
+ ],
+ ),
+ migrations.AddField(
+ model_name='installedpackages',
+ name='phpVers',
+ field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='managePHP.PHP'),
+ ),
+ ]
diff --git a/packages/migrations/0001_initial.py b/packages/migrations/0001_initial.py
new file mode 100644
index 000000000..a5eb96042
--- /dev/null
+++ b/packages/migrations/0001_initial.py
@@ -0,0 +1,32 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11 on 2019-01-07 12:43
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+ initial = True
+
+ dependencies = [
+ ('loginSystem', '0001_initial'),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='Package',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('packageName', models.CharField(max_length=50, unique=True)),
+ ('diskSpace', models.IntegerField()),
+ ('bandwidth', models.IntegerField()),
+ ('emailAccounts', models.IntegerField(null=True)),
+ ('dataBases', models.IntegerField(default=0)),
+ ('ftpAccounts', models.IntegerField(default=0)),
+ ('allowedDomains', models.IntegerField(default=0)),
+ ('admin', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='loginSystem.Administrator')),
+ ],
+ ),
+ ]
diff --git a/plogical/acl.py b/plogical/acl.py
index 5902cf3b7..0d37f468c 100644
--- a/plogical/acl.py
+++ b/plogical/acl.py
@@ -8,6 +8,7 @@ from loginSystem.models import Administrator, ACL
from django.shortcuts import HttpResponse
from packages.models import Package
from websiteFunctions.models import Websites, ChildDomains
+from dockerManager.models import Containers
from dns.models import Domains
import json
from subprocess import call, CalledProcessError
@@ -104,6 +105,9 @@ class ACLManager:
finalResponse['manageSSL'] = acl.manageSSL
finalResponse['hostnameSSL'] = acl.hostnameSSL
finalResponse['mailServerSSL'] = acl.mailServerSSL
+
+ # Container Management
+ finalResponse['assignContainer'] = acl.assignContainer
return finalResponse
@@ -230,24 +234,6 @@ class ACLManager:
adminNames.append(admin.userName)
return adminNames
- @staticmethod
- def loadUserObjects(userID):
- admin = Administrator.objects.get(pk=userID)
- adminObjects = []
-
- finalResponse = ACLManager.loadedACL(userID)
-
- if finalResponse['admin'] == 1:
- return Administrator.objects.all()
- else:
- admins = Administrator.objects.filter(owner=admin.pk)
- for items in admins:
- adminObjects.append(items)
-
- adminObjects.append(admin)
-
- return adminObjects
-
@staticmethod
def loadDeletionUsers(userID, finalResponse):
admin = Administrator.objects.get(pk=userID)
@@ -329,15 +315,6 @@ class ACLManager:
return packNames
- @staticmethod
- def loadPackageObjects(userID, finalResponse):
- admin = Administrator.objects.get(pk=userID)
-
- if finalResponse['admin'] == 1:
- return Package.objects.all()
- else:
- return admin.package_set.all()
-
@staticmethod
def findAllSites(currentACL, userID):
websiteNames = []
@@ -362,6 +339,30 @@ class ACLManager:
return websiteNames
+
+ @staticmethod
+ def findAllContainers(currentACL, userID):
+ containerName = []
+
+ if currentACL['admin'] == 1:
+ allContainers = Containers.objects.all()
+ for items in allContainers:
+ containerName.append(items.name)
+ else:
+ admin = Administrator.objects.get(pk=userID)
+
+ containers = admin.containers_set.all()
+ admins = Administrator.objects.filter(owner=admin.pk)
+
+ for items in containers:
+ containerName.append(items.name)
+
+ for items in admins:
+ cons = items.containers_set.all()
+ for con in cons:
+ containerName.append(con.name)
+
+ return containerName
@staticmethod
def findWebsiteObjects(currentACL, userID):
@@ -386,6 +387,30 @@ class ACLManager:
websiteList.append(web)
return websiteList
+
+ @staticmethod
+ def findContainersObjects(currentACL, userID):
+
+ if currentACL['admin'] == 1:
+ return Containers.objects.all()
+ else:
+
+ containerList = []
+ admin = Administrator.objects.get(pk=userID)
+
+ containers = admin.containers_set.all()
+
+ for items in containers:
+ containerList.append(items)
+
+ admins = Administrator.objects.filter(owner=admin.pk)
+
+ for items in admins:
+ cons = items.containers_set.all()
+ for con in cons:
+ containerList.append(web)
+
+ return containerList
@staticmethod
def findAllDomains(currentACL, userID):
@@ -437,6 +462,22 @@ class ACLManager:
return 1
else:
return 0
+
+ @staticmethod
+ def checkContainerOwnership(name, userID):
+ try:
+ container = Containers.objects.get(name=name)
+ currentACL = ACLManager.loadedACL(userID)
+ admin = Administrator.objects.get(pk=userID)
+
+ if currentACL['admin'] == 1:
+ return 1
+ elif container.admin == admin:
+ return 1
+ else:
+ return 0
+ except:
+ return 0
@staticmethod
def executeCall(command):
diff --git a/plogical/container.py b/plogical/container.py
new file mode 100644
index 000000000..bcbce204e
--- /dev/null
+++ b/plogical/container.py
@@ -0,0 +1,938 @@
+#!/usr/local/CyberCP/bin/python2
+from __future__ import division
+import os
+import os.path
+import sys
+import django
+import mimetypes
+sys.path.append('/usr/local/CyberCP')
+os.environ.setdefault("DJANGO_SETTINGS_MODULE", "CyberCP.settings")
+django.setup()
+import json
+from acl import ACLManager
+import CyberCPLogFileWriter as logging
+from django.shortcuts import HttpResponse, render
+from loginSystem.models import Administrator, ACL
+import subprocess
+import shlex
+import time
+from dockerManager.models import Containers
+from django.http import StreamingHttpResponse
+from wsgiref.util import FileWrapper
+from math import ceil
+import docker
+import docker.utils
+import requests
+
+# Use default socket to connect
+client = docker.from_env()
+dockerAPI = docker.APIClient()
+
+class ContainerManager:
+ def __init__(self, name = None):
+ self.name = name
+
+ def submitInstallDocker(self, userID = None, data = None):
+ try:
+ currentACL = ACLManager.loadedACL(userID)
+ if ACLManager.currentContextPermission(currentACL, 'createContainer') == 0:
+ return ACLManager.loadError()
+
+ command = 'yum install -y docker'
+ cmd = shlex.split(command)
+ res = subprocess.call(cmd)
+
+ if res == 0:
+ data_ret = {'installDockerStatus': 1, 'error_message': 'None'}
+ json_data = json.dumps(data_ret)
+ return HttpResponse(json_data)
+ else:
+ data_ret = {'installDockerStatus': 0, 'error_message': 'Failed to install. Manual install required.'}
+ json_data = json.dumps(data_ret)
+ return HttpResponse(json_data)
+
+ return HttpResponse(res)
+
+ except BaseException, msg:
+ return HttpResponse(str(msg))
+
+ def createContainer(self, request = None, userID = None, data = None):
+ try:
+ currentACL = ACLManager.loadedACL(userID)
+ if ACLManager.currentContextPermission(currentACL, 'createContainer') == 0:
+ return ACLManager.loadError()
+
+ adminNames = ACLManager.loadAllUsers(userID)
+ tag = request.GET.get('tag')
+ image = request.GET.get('image')
+ tag = tag.split(" (")[0]
+
+ if "/" in image:
+ name = image.split("/")[0] + "." + image.split("/")[1]
+ else:
+ name = image
+
+ try:
+ inspectImage = dockerAPI.inspect_image(image+":"+tag)
+ except docker.errors.ImageNotFound:
+ val = request.session['userID']
+ admin = Administrator.objects.get(pk=val)
+ return render(request,'dockerManager/images.html',{"type":admin.type,
+ 'image':image,
+ 'tag':tag})
+
+ envList = {};
+ if 'Env' in inspectImage['Config']:
+ for item in inspectImage['Config']['Env']:
+ if '=' in item:
+ splitedItem = item.split('=',1)
+ print splitedItem
+ envList[splitedItem[0]] = splitedItem[1]
+ else:
+ envList[item] = ""
+
+ portConfig = {};
+ if 'ExposedPorts' in inspectImage['Config']:
+ for item in inspectImage['Config']['ExposedPorts']:
+ portDef = item.split('/')
+ portConfig[portDef[0]] = portDef[1]
+
+ print portConfig
+ if image is None or image is '' or tag is None or tag is '':
+ return redirect(loadImages)
+
+ Data = {"ownerList": adminNames, "image":image, "name":name, "tag":tag, "portConfig": portConfig, "envList":envList}
+
+ return render(request, 'dockerManager/runContainer.html', Data)
+
+ except BaseException, msg:
+ return HttpResponse(str(msg))
+
+ def loadContainerHome(self, request = None, userID = None, data = None):
+ name = self.name
+
+ if ACLManager.checkContainerOwnership(name, userID) != 1:
+ return ACLManager.loadError()
+
+ try:
+ container = client.containers.get(name)
+ except docker.errors.NotFound as err:
+ return HttpResponse("Container not found")
+
+ data = {}
+ con = Containers.objects.get(name=name)
+ data['name'] = name
+ data['image'] = con.image + ":" + con.tag
+ data['ports'] = json.loads(con.ports)
+ data['cid'] = con.cid
+ data['envList'] = json.loads(con.env)
+ print data['envList']
+
+ stats = container.stats(decode=False, stream=False)
+ logs = container.logs(stream=True)
+
+ data['status'] = container.status
+ data['memoryLimit'] = con.memory
+ if con.startOnReboot == 1:
+ data['startOnReboot'] = 'true'
+ data['restartPolicy'] = "Yes"
+ else:
+ data['startOnReboot'] = 'false'
+ data['restartPolicy'] = "No"
+
+ if 'usage' in stats['memory_stats']:
+ # Calculate Usage
+ # Source: https://github.com/docker/docker/blob/28a7577a029780e4533faf3d057ec9f6c7a10948/api/client/stats.go#L309
+ data['memoryUsage'] = (stats['memory_stats']['usage'] / stats['memory_stats']['limit']) * 100
+
+ cpu_count = len(stats["cpu_stats"]["cpu_usage"]["percpu_usage"])
+ data['cpuUsage'] = 0.0
+ cpu_delta = float(stats["cpu_stats"]["cpu_usage"]["total_usage"]) - \
+ float(stats["precpu_stats"]["cpu_usage"]["total_usage"])
+ system_delta = float(stats["cpu_stats"]["system_cpu_usage"]) - \
+ float(stats["precpu_stats"]["system_cpu_usage"])
+ if system_delta > 0.0:
+ data['cpuUsage'] = round(cpu_delta / system_delta * 100.0 * cpu_count, 3)
+ else:
+ data['memoryUsage'] = 0
+ data['cpuUsage'] = 0;
+
+ return render(request, 'dockerManager/viewContainer.html', data)
+
+ def listContainers(self, request = None, userID = None, data = None):
+ try:
+ currentACL = ACLManager.loadedACL(userID)
+ containers = ACLManager.findAllContainers(currentACL, userID)
+
+ allContainers = client.containers.list()
+ containersList = []
+ showUnlistedContainer = True
+
+ # TODO: Add condition to show unlisted Containers only if user has admin level access
+
+ unlistedContainers = []
+ for container in allContainers:
+ if container.name not in containers:
+ unlistedContainers.append(container)
+
+ if not unlistedContainers:
+ showUnlistedContainer = False
+
+ adminNames = ACLManager.loadAllUsers(userID)
+
+ pages = float(len(containers)) / 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, 'dockerManager/listContainers.html', {"pagination": pagination,
+ "unlistedContainers": unlistedContainers,
+ "adminNames": adminNames,
+ "showUnlistedContainer":showUnlistedContainer})
+ except BaseException, msg:
+ return HttpResponse(str(msg))
+
+ def getContainerLogs(self, userID = None, data = None):
+ try:
+ name = data['name']
+
+ # Check if container is registered in database or unlisted
+ if Containers.objects.filter(name=name).exists():
+ if ACLManager.checkContainerOwnership(name, userID) != 1:
+ return ACLManager.loadErrorJson('containerLogStatus',0)
+
+ container = client.containers.get(name)
+ logs = container.logs()
+
+ data_ret = {'containerLogStatus': 1, 'containerLog': logs, 'error_message': "None"}
+ json_data = json.dumps(data_ret)
+ return HttpResponse(json_data)
+
+
+ except BaseException, msg:
+ data_ret = {'containerLogStatus': 0, 'containerLog':'Error', 'error_message': str(msg)}
+ json_data = json.dumps(data_ret)
+ return HttpResponse(json_data)
+
+ def submitContainerCreation(self, userID = None, data = None):
+ try:
+
+ currentACL = ACLManager.loadedACL(userID)
+ if ACLManager.currentContextPermission(currentACL, 'createWebsite') == 0:
+ return ACLManager.loadErrorJson('createWebSiteStatus', 0)
+
+ name = data['name']
+ image = data['image']
+ tag = data['tag']
+ dockerOwner = data['dockerOwner']
+ memory = data['memory']
+ envList = data['envList']
+
+ inspectImage = dockerAPI.inspect_image(image+":"+tag)
+ portConfig = {}
+
+ # Formatting envList for usage
+ envDict = {}
+ for key, value in envList.iteritems():
+ if (value['name'] != '') or (value['value'] != ''):
+ envDict[value['name']] = value['value']
+
+ if 'ExposedPorts' in inspectImage['Config']:
+ for item in inspectImage['Config']['ExposedPorts']:
+ # Do not allow priviledged port numbers
+ if int(data[item]) < 1024 or int(data[item]) > 65535:
+ data_ret = {'createContainerStatus': 0, 'error_message': "Choose port between 1024 and 65535"}
+ json_data = json.dumps(data_ret)
+ return HttpResponse(json_data)
+ portConfig[item] = data[item]
+
+ ## Create Configurations
+ admin = Administrator.objects.get(userName=dockerOwner)
+
+ containerArgs = {'image':image+":"+tag,
+ 'detach':True,
+ 'name':name,
+ 'ports':portConfig,
+ 'publish_all_ports': True,
+ 'environment':envDict}
+
+ containerArgs['mem_limit'] = memory * 1048576; # Converts MB to bytes ( 0 * x = 0 for unlimited memory)
+
+ try:
+ container = client.containers.create(**containerArgs)
+ except Exception as err:
+ if "port is already allocated" in err: # We need to delete container if port is not available
+ print "Deleting container"
+ container.remove(force=True)
+ data_ret = {'createContainerStatus': 0, 'error_message': str(err)}
+ json_data = json.dumps(data_ret)
+ return HttpResponse(json_data)
+
+ con = Containers(admin=admin,
+ name=name,
+ tag=tag,
+ image=image,
+ memory=memory,
+ ports=json.dumps(portConfig),
+ env=json.dumps(envDict),
+ cid=container.id)
+
+ con.save()
+
+ data_ret = {'createContainerStatus': 1, 'error_message': "None"}
+ json_data = json.dumps(data_ret)
+ return HttpResponse(json_data)
+
+
+ except BaseException, msg:
+ data_ret = {'createContainerStatus': 0, 'error_message': str(msg)}
+ json_data = json.dumps(data_ret)
+ return HttpResponse(json_data)
+
+ def submitInstallImage(self, userID = None, data = None):
+ try:
+
+ currentACL = ACLManager.loadedACL(userID)
+ if ACLManager.currentContextPermission(currentACL, 'createWebsite') == 0:
+ return ACLManager.loadErrorJson('createWebSiteStatus', 0)
+
+ image = data['image']
+ tag = data['tag']
+
+ try:
+ inspectImage = dockerAPI.inspect_image(image+":"+tag)
+ data_ret = {'installImageStatus': 0, 'error_message': "Image already installed"}
+ json_data = json.dumps(data_ret)
+ return HttpResponse(json_data)
+ except docker.errors.ImageNotFound:
+ pass
+
+ try:
+ image = client.images.pull(image, tag=tag)
+ print image.id
+ except docker.errors.APIError as msg:
+ data_ret = {'installImageStatus': 0, 'error_message': str(msg)}
+ json_data = json.dumps(data_ret)
+ return HttpResponse(json_data)
+
+
+ data_ret = {'installImageStatus': 1, 'error_message': "None"}
+ json_data = json.dumps(data_ret)
+ return HttpResponse(json_data)
+
+
+ except BaseException, msg:
+ data_ret = {'installImageStatus': 0, 'error_message': str(msg)}
+ json_data = json.dumps(data_ret)
+ return HttpResponse(json_data)
+
+ def submitContainerDeletion(self, userID = None, data = None, called = False):
+ try:
+ name = data['name']
+ # Check if container is registered in database or unlisted
+ if Containers.objects.filter(name=name).exists():
+ if ACLManager.checkContainerOwnership(name, userID) != 1:
+ if called:
+ return 'Permission error'
+ else:
+ return ACLManager.loadErrorJson('websiteDeleteStatus', 0)
+
+ unlisted = data['unlisted']
+
+ if 'force' in data:
+ force = True
+ else:
+ force = False
+
+ if not unlisted:
+ containerOBJ = Containers.objects.get(name=name)
+
+ if not force:
+ try:
+ container = client.containers.get(name)
+ except docker.errors.NotFound as err:
+ if called:
+ return 'Container does not exist'
+ else:
+ data_ret = {'delContainerStatus': 2, 'error_message': 'Container does not exist'}
+ json_data = json.dumps(data_ret)
+ return HttpResponse(json_data)
+
+ try:
+ container.stop() # Stop container
+ container.kill() # INCASE graceful stop doesn't work
+ except:
+ pass
+
+ try:
+ container.remove() # Finally remove container
+ except docker.errors.APIError as err:
+ data_ret = {'delContainerStatus': 0, 'error_message': str(err)}
+ json_data = json.dumps(data_ret)
+ return HttpResponse(json_data)
+ except:
+ if called:
+ return "Unknown"
+ else:
+ data_ret = {'delContainerStatus': 0, 'error_message': 'Unknown error'}
+ json_data = json.dumps(data_ret)
+ return HttpResponse(json_data)
+
+ if not unlisted and not called:
+ containerOBJ.delete()
+
+ if called:
+ return 0
+ else:
+ data_ret = {'delContainerStatus': 1, 'error_message': "None"}
+ json_data = json.dumps(data_ret)
+ return HttpResponse(json_data)
+
+ except BaseException, msg:
+ if called:
+ return str(msg)
+ else:
+ data_ret = {'delContainerStatus': 0, 'error_message': str(msg)}
+ json_data = json.dumps(data_ret)
+ return HttpResponse(json_data)
+
+ def getContainerList(self, userID = None, data = None):
+ try:
+ currentACL = ACLManager.loadedACL(userID)
+ pageNumber = int(data['page'])
+ json_data = self.findContainersJson(currentACL, userID, pageNumber)
+ final_dic = {'listContainerStatus': 1, 'error_message': "None", "data": json_data}
+ final_json = json.dumps(final_dic)
+ return HttpResponse(final_json)
+ except BaseException, msg:
+ dic = {'listContainerStatus': 0, 'error_message': str(msg)}
+ json_data = json.dumps(dic)
+ return HttpResponse(json_data)
+
+ def findContainersJson(self, currentACL, userID, pageNumber):
+ finalPageNumber = ((pageNumber * 10)) - 10
+ endPageNumber = finalPageNumber + 10
+ containers = ACLManager.findContainersObjects(currentACL, userID)[finalPageNumber:endPageNumber]
+
+ json_data = "["
+ checker = 0
+
+ for items in containers:
+ dic = {'name': items.name,'admin': items.admin.userName, 'tag':items.tag, 'image':items.image}
+
+ if checker == 0:
+ json_data = json_data + json.dumps(dic)
+ checker = 1
+ else:
+ json_data = json_data + ',' + json.dumps(dic)
+
+ json_data = json_data + ']'
+
+ return json_data
+
+ def doContainerAction(self, userID = None, data = None):
+ try:
+
+ name = data['name']
+ if ACLManager.checkContainerOwnership(name, userID) != 1:
+ return ACLManager.loadErrorJson('containerActionStatus',0)
+
+ action = data['action']
+ try:
+ container = client.containers.get(name)
+ except docker.errors.NotFound as err:
+ data_ret = {'containerActionStatus': 0, 'error_message': 'Container does not exist'}
+ json_data = json.dumps(data_ret)
+ return HttpResponse(json_data)
+ except:
+ data_ret = {'containerActionStatus': 0, 'error_message': 'Unknown'}
+ json_data = json.dumps(data_ret)
+ return HttpResponse(json_data)
+
+ try:
+ if action == 'start':
+ container.start()
+ elif action == 'stop':
+ container.stop()
+ elif action == 'restart':
+ container.restart()
+ else:
+ data_ret = {'containerActionStatus': 0, 'error_message': 'Unknown Action'}
+ json_data = json.dumps(data_ret)
+ return HttpResponse(json_data)
+ except docker.errors.APIError as err:
+ data_ret = {'containerActionStatus': 0, 'error_message': str(err)}
+ json_data = json.dumps(data_ret)
+ return HttpResponse(json_data)
+
+ time.sleep(3) # Wait 3 seconds for container to finish starting/stopping/restarting
+ status = container.status
+ data_ret = {'containerActionStatus': 1, 'error_message': 'None', 'status': status}
+ json_data = json.dumps(data_ret)
+ return HttpResponse(json_data)
+
+ except BaseException, msg:
+ data_ret = {'containerActionStatus': 0, 'error_message': str(msg)}
+ json_data = json.dumps(data_ret)
+ return HttpResponse(json_data)
+
+ def getContainerStatus(self, userID = None, data = None):
+ try:
+ name = data['name']
+ if ACLManager.checkContainerOwnership(name, userID) != 1:
+ return ACLManager.loadErrorJson('containerStatus',0)
+
+ try:
+ container = client.containers.get(name)
+ except docker.errors.NotFound as err:
+ data_ret = {'containerStatus': 0, 'error_message': 'Container does not exist'}
+ json_data = json.dumps(data_ret)
+ return HttpResponse(json_data)
+ except:
+ data_ret = {'containerStatus': 0, 'error_message': 'Unknown'}
+ json_data = json.dumps(data_ret)
+ return HttpResponse(json_data)
+
+ status = container.status
+ data_ret = {'containerStatus': 1, 'error_message': 'None', 'status': status}
+ json_data = json.dumps(data_ret)
+ return HttpResponse(json_data)
+
+ except BaseException, msg:
+ data_ret = {'containerStatus': 0, 'error_message': str(msg)}
+ json_data = json.dumps(data_ret)
+ return HttpResponse(json_data)
+
+ def exportContainer(self, request = None, userID = None, data = None):
+ try:
+ name = request.GET.get('name')
+ if ACLManager.checkContainerOwnership(name, userID) != 1:
+ return ACLManager.loadErrorJson('containerStatus',0)
+
+ try:
+ container = client.containers.get(name)
+ except docker.errors.NotFound as err:
+ data_ret = {'containerStatus': 0, 'error_message': 'Container does not exist'}
+ json_data = json.dumps(data_ret)
+ return HttpResponse(json_data)
+ except:
+ data_ret = {'containerStatus': 0, 'error_message': 'Unknown'}
+ json_data = json.dumps(data_ret)
+ return HttpResponse(json_data)
+
+ eFile = container.export() # Export with default chunk size
+ response = HttpResponse(eFile, content_type='application/force-download')
+ response['Content-Disposition'] = 'attachment; filename="'+ name +'.tar"'
+ return response
+
+ except BaseException, msg:
+ data_ret = {'containerStatus': 0, 'error_message': str(msg)}
+ json_data = json.dumps(data_ret)
+ return HttpResponse(json_data)
+
+ def getContainerTop(self, userID = None, data = None):
+ try:
+ name = data['name']
+ if ACLManager.checkContainerOwnership(name, userID) != 1:
+ return ACLManager.loadErrorJson('containerTopStatus',0)
+ try:
+ container = client.containers.get(name)
+ except docker.errors.NotFound as err:
+ data_ret = {'containerTopStatus': 0, 'error_message': 'Container does not exist'}
+ json_data = json.dumps(data_ret)
+ return HttpResponse(json_data)
+ except:
+ data_ret = {'containerTopStatus': 0, 'error_message': 'Unknown'}
+ json_data = json.dumps(data_ret)
+ return HttpResponse(json_data)
+
+ try:
+ top = container.top()
+ except docker.errors.APIError as err:
+ data_ret = {'containerTopStatus': 0, 'error_message': str(err)}
+ json_data = json.dumps(data_ret)
+ return HttpResponse(json_data)
+
+ data_ret = {'containerTopStatus': 1, 'error_message': 'None', 'processes':top}
+ json_data = json.dumps(data_ret)
+ return HttpResponse(json_data)
+
+ except BaseException, msg:
+ data_ret = {'containerTopStatus': 0, 'error_message': str(msg)}
+ json_data = json.dumps(data_ret)
+ return HttpResponse(json_data)
+
+ def assignContainer(self, userID = None, data = None):
+ try:
+ # Todo: add check only for super user i.e. main admin
+ name = data['name']
+ dockerOwner = data['admin']
+
+ admin = Administrator.objects.get(userName=dockerOwner)
+
+ try:
+ container = client.containers.get(name)
+ except docker.errors.NotFound as err:
+ data_ret = {'assignContainerStatus': 0, 'error_message': 'Container does not exist'}
+ json_data = json.dumps(data_ret)
+ return HttpResponse(json_data)
+ except:
+ data_ret = {'assignContainerStatus': 0, 'error_message': 'Unknown'}
+ json_data = json.dumps(data_ret)
+ return HttpResponse(json_data)
+
+ con = Containers(admin=admin,
+ name=name,
+ cid=container.id)
+
+ con.save()
+
+ data_ret = {'assignContainerStatus': 1, 'error_message': 'None'}
+ json_data = json.dumps(data_ret)
+ return HttpResponse(json_data)
+
+ except BaseException, msg:
+ data_ret = {'assignContainerStatus': 0, 'error_message': str(msg)}
+ json_data = json.dumps(data_ret)
+ return HttpResponse(json_data)
+
+ def searchImage(self, userID = None, data = None):
+ try:
+ string = data['string']
+ try:
+ matches = client.images.search(term=string)
+ except docker.errors.APIError as err:
+ data_ret = {'searchImageStatus': 0, 'error_message': str(err)}
+ json_data = json.dumps(data_ret)
+ return HttpResponse(json_data)
+ except:
+ data_ret = {'searchImageStatus': 0, 'error_message': 'Unknown'}
+ json_data = json.dumps(data_ret)
+ return HttpResponse(json_data)
+
+ print json.dumps(matches)
+
+ for image in matches:
+ if "/" in image['name']:
+ image['name2'] = image['name'].split("/")[0] + ":" + image['name'].split("/")[1]
+ else:
+ image['name2'] = image['name']
+
+
+ data_ret = {'searchImageStatus': 1, 'error_message': 'None', 'matches':matches}
+ json_data = json.dumps(data_ret)
+ return HttpResponse(json_data)
+
+ except BaseException, msg:
+ data_ret = {'searchImageStatus': 0, 'error_message': str(msg)}
+ json_data = json.dumps(data_ret)
+ return HttpResponse(json_data)
+
+ def images(self, request = None, userID = None, data = None):
+ try:
+ try:
+ imageList = client.images.list()
+ except docker.errors.APIError as err:
+ return HttpResponse(str(err))
+
+ images = {}
+ names = []
+
+ for image in imageList:
+ name = image.attrs['RepoTags'][0].split(":")[0]
+ if "/" in name:
+ name2 = ""
+ for item in name.split("/"):
+ name2 += ":" + item
+ else:
+ name2 = name
+
+ tags = []
+ for tag in image.tags:
+ getTag = tag.split(":")
+ if len(getTag) == 2:
+ tags.append(getTag[1])
+ print tags
+ if name in names:
+ images[name]['tags'].extend(tags)
+ else:
+ names.append(name)
+ images[name] = {"name":name,
+ "name2":name2,
+ "tags":tags}
+ print "======"
+ print images
+ return render(request, 'dockerManager/images.html', {"images":images, "test":'asds'})
+
+ except BaseException, msg:
+ return HttpResponse(str(msg))
+
+ def manageImages(self, request = None, userID = None, data = None):
+ try:
+ imageList = client.images.list()
+
+ images = {}
+ names = []
+
+ for image in imageList:
+ name = image.attrs['RepoTags'][0].split(":")[0]
+ if name in names:
+ images[name]['tags'].extend(image.tags)
+ else:
+ names.append(name)
+ tags = []
+ images[name] = {"name":name,
+ "tags":image.tags}
+ return render(request, 'dockerManager/manageImages.html', {"images":images})
+
+ except BaseException, msg:
+ return HttpResponse(str(msg))
+
+ def getImageHistory(self, userID = None, data = None):
+ try:
+
+ name = data['name']
+ try:
+ image = client.images.get(name)
+ except docker.errors.APIError as err:
+ data_ret = {'imageHistoryStatus': 0, 'error_message': str(err)}
+ json_data = json.dumps(data_ret)
+ return HttpResponse(json_data)
+ except:
+ data_ret = {'imageHistoryStatus': 0, 'error_message': 'Unknown'}
+ json_data = json.dumps(data_ret)
+ return HttpResponse(json_data)
+
+
+
+ data_ret = {'imageHistoryStatus': 1, 'error_message': 'None', 'history':image.history()}
+ json_data = json.dumps(data_ret)
+ return HttpResponse(json_data)
+
+ except BaseException, msg:
+ data_ret = {'imageHistoryStatus': 0, 'error_message': str(msg)}
+ json_data = json.dumps(data_ret)
+ return HttpResponse(json_data)
+
+ def removeImage(self, userID = None, data = None):
+ try:
+ name = data['name']
+ try:
+ if name == 0:
+ action = client.images.prune()
+ else:
+ action = client.images.remove(name)
+ print action
+ except docker.errors.APIError as err:
+ data_ret = {'removeImageStatus': 0, 'error_message': str(err)}
+ json_data = json.dumps(data_ret)
+ return HttpResponse(json_data)
+ except:
+ data_ret = {'removeImageStatus': 0, 'error_message': 'Unknown'}
+ json_data = json.dumps(data_ret)
+ return HttpResponse(json_data)
+
+
+
+ data_ret = {'removeImageStatus': 1, 'error_message': 'None'}
+ json_data = json.dumps(data_ret)
+ return HttpResponse(json_data)
+
+ except BaseException, msg:
+ data_ret = {'removeImageStatus': 0, 'error_message': str(msg)}
+ json_data = json.dumps(data_ret)
+ return HttpResponse(json_data)
+
+ # Internal function for recreating containers
+
+ def doRecreateContainer(self, userID, data, con):
+ try:
+ name = data['name']
+ unlisted = data['unlisted'] # Pass this as 1 if image is not known for container
+ image = data['image']
+ tag = data['tag']
+ env = data['env']
+ port = data['ports']
+ memory = data['memory']
+
+ if image == 'unknown':
+ return "Image name not known"
+ # Call container delete function
+ delStatus = self.submitContainerDeletion(userID, data, True)
+ if delStatus != 0:
+ return delStatus
+
+ print env
+ containerArgs = {'image':image+":"+tag,
+ 'detach':True,
+ 'name':name,
+ 'ports':port,
+ 'environment':env,
+ 'publish_all_ports': True,
+ 'mem_limit': memory * 1048576}
+
+ if con.startOnReboot == 1:
+ containerArgs['restart_policy'] = {"Name": "always"}
+
+ container = client.containers.create(**containerArgs)
+ con.cid = container.id
+ con.save()
+
+ return 0
+ except BaseException, msg:
+ return str(msg)
+
+ def saveContainerSettings(self, userID = None, data = None):
+ try:
+ name = data['name']
+ if ACLManager.checkContainerOwnership(name, userID) != 1:
+ return ACLManager.loadErrorJson('saveSettingsStatus',0)
+
+ memory = data['memory']
+ startOnReboot = data['startOnReboot']
+ envList = data['envList']
+
+ if startOnReboot == True:
+ startOnReboot = 1
+ rPolicy = {"Name": "always"}
+ else:
+ startOnReboot = 0
+ rPolicy = {}
+
+ try:
+ container = client.containers.get(name)
+ except docker.errors.NotFound as err:
+ data_ret = {'saveSettingsStatus': 0, 'error_message': 'Container does not exist'}
+ json_data = json.dumps(data_ret)
+ return HttpResponse(json_data)
+ except:
+ data_ret = {'saveSettingsStatus': 0, 'error_message': 'Unknown'}
+ json_data = json.dumps(data_ret)
+ return HttpResponse(json_data)
+
+ try:
+ container.update(mem_limit=memory * 1048576,
+ restart_policy = rPolicy)
+ except docker.errors.APIError as err:
+ data_ret = {'saveSettingsStatus': 0, 'error_message': str(err)}
+ json_data = json.dumps(data_ret)
+ return HttpResponse(json_data)
+
+ con = Containers.objects.get(name=name)
+ con.memory = memory
+ con.startOnReboot = startOnReboot
+
+ if 'envConfirmation' in data and data['envConfirmation']:
+ # Formatting envList for usage
+ envDict = {}
+ for key, value in envList.iteritems():
+ if (value['name'] != '') or (value['value'] != ''):
+ envDict[value['name']] = value['value']
+
+ print envDict
+ # Prepare data for recreate function
+ data = {
+ 'name': name,
+ 'unlisted': 0,
+ 'image': con.image,
+ 'tag': con.tag,
+ 'env': envDict,
+ 'ports': json.loads(con.ports), # No filter needed now as its ports are filtered when adding to database
+ 'memory': con.memory
+ }
+
+ recreateStatus = self.doRecreateContainer(userID, data, con)
+ if recreateStatus != 0:
+ data_ret = {'saveSettingsStatus': 0, 'error_message': str(recreateStatus)}
+ json_data = json.dumps(data_ret)
+ return HttpResponse(json_data)
+
+ con.env = json.dumps(envDict)
+ con.save()
+
+ data_ret = {'saveSettingsStatus': 1, 'error_message': 'None'}
+ json_data = json.dumps(data_ret)
+ return HttpResponse(json_data)
+
+ except BaseException, msg:
+ data_ret = {'saveSettingsStatus': 0, 'error_message': str(msg)}
+ json_data = json.dumps(data_ret)
+ return HttpResponse(json_data)
+
+ def recreateContainer(self, userID = None, data = None):
+ try:
+ name = data['name']
+ if ACLManager.checkContainerOwnership(name, userID) != 1:
+ return ACLManager.loadErrorJson('saveSettingsStatus',0)
+
+ try:
+ container = client.containers.get(name)
+ except docker.errors.NotFound as err:
+ data_ret = {'recreateContainerStatus': 0, 'error_message': 'Container does not exist'}
+ json_data = json.dumps(data_ret)
+ return HttpResponse(json_data)
+ except:
+ data_ret = {'recreateContainerStatus': 0, 'error_message': 'Unknown'}
+ json_data = json.dumps(data_ret)
+ return HttpResponse(json_data)
+
+ con = Containers.objects.get(name=name)
+
+ # Prepare data for recreate function
+ data = {
+ 'name': name,
+ 'unlisted': 0,
+ 'image': con.image,
+ 'tag': con.tag,
+ 'env': json.loads(con.env),
+ 'ports': json.loads(con.ports), # No filter needed now as its ports are filtered when adding to database
+ 'memory': con.memory
+ }
+
+ recreateStatus = self.doRecreateContainer(userID, data, con)
+ if recreateStatus != 0:
+ data_ret = {'recreateContainerStatus': 0, 'error_message': str(recreateStatus)}
+ json_data = json.dumps(data_ret)
+ return HttpResponse(json_data)
+
+ data_ret = {'recreateContainerStatus': 1, 'error_message': 'None'}
+ json_data = json.dumps(data_ret)
+ return HttpResponse(json_data)
+
+ except BaseException, msg:
+ data_ret = {'recreateContainerStatus': 0, 'error_message': str(msg)}
+ json_data = json.dumps(data_ret)
+ return HttpResponse(json_data)
+
+ def getTags(self, userID = None, data = None):
+ try:
+ image = data['image']
+ page = data['page']
+
+ if ":" in image:
+ image2 = image.split(":")[0] + "/" + image.split(":")[1]
+ else:
+ image2 = "library/" + image
+
+ print image
+ registryData = requests.get('https://registry.hub.docker.com/v2/repositories/'+image2+'/tags', {'page':page}).json()
+
+ tagList = []
+ for tag in registryData['results']:
+ tagList.append(tag['name'])
+
+ data_ret = {'getTagsStatus': 1, 'list': tagList, 'next':registryData['next'], 'error_message': None}
+ json_data = json.dumps(data_ret)
+ return HttpResponse(json_data)
+ except BaseException, msg:
+ data_ret = {'getTagsStatus': 0, 'error_message': str(msg)}
+ json_data = json.dumps(data_ret)
+ return HttpResponse(json_data)
\ No newline at end of file
diff --git a/websiteFunctions/migrations/0001_initial.py b/websiteFunctions/migrations/0001_initial.py
new file mode 100644
index 000000000..69a2f29fa
--- /dev/null
+++ b/websiteFunctions/migrations/0001_initial.py
@@ -0,0 +1,94 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11 on 2019-01-07 12:43
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+ initial = True
+
+ dependencies = [
+ ('packages', '0001_initial'),
+ ('loginSystem', '0001_initial'),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='aliasDomains',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('aliasDomain', models.CharField(max_length=75)),
+ ],
+ ),
+ migrations.CreateModel(
+ name='Backups',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('fileName', models.CharField(max_length=50)),
+ ('date', models.CharField(max_length=50)),
+ ('size', models.CharField(max_length=50)),
+ ('status', models.IntegerField(default=0)),
+ ],
+ ),
+ migrations.CreateModel(
+ name='backupSchedules',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('frequency', models.CharField(max_length=15)),
+ ],
+ ),
+ migrations.CreateModel(
+ name='ChildDomains',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('domain', models.CharField(max_length=50, unique=True)),
+ ('path', models.CharField(default=None, max_length=200)),
+ ('ssl', models.IntegerField()),
+ ('phpSelection', models.CharField(default=None, max_length=10)),
+ ],
+ ),
+ migrations.CreateModel(
+ name='dest',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('destLoc', models.CharField(max_length=18, unique=True)),
+ ],
+ ),
+ migrations.CreateModel(
+ name='Websites',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('domain', models.CharField(max_length=50, unique=True)),
+ ('adminEmail', models.CharField(max_length=50)),
+ ('phpSelection', models.CharField(max_length=10)),
+ ('ssl', models.IntegerField()),
+ ('state', models.IntegerField(default=1)),
+ ('externalApp', models.CharField(default=None, max_length=10)),
+ ('admin', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='loginSystem.Administrator')),
+ ('package', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='packages.Package')),
+ ],
+ ),
+ migrations.AddField(
+ model_name='childdomains',
+ name='master',
+ field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='websiteFunctions.Websites'),
+ ),
+ migrations.AddField(
+ model_name='backupschedules',
+ name='dest',
+ field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='websiteFunctions.dest'),
+ ),
+ migrations.AddField(
+ model_name='backups',
+ name='website',
+ field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='websiteFunctions.Websites'),
+ ),
+ migrations.AddField(
+ model_name='aliasdomains',
+ name='master',
+ field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='websiteFunctions.Websites'),
+ ),
+ ]