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 }} +


+ +
+ + + + + + + + + + + + {% for name, image in images.items %} + + + + + + + {% endfor %} + + +
Name (Installed)TagsAction
{{image.name}} + + + {% trans "Create" %} +
+ +
+
+
+ + + +{% 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" %}

+
+ + + +
+ + +{% 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 %} + + {% 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" %} +

+
+ + + + + + + + + + + + + + + + + + + + + + + + +
NameLaunchOwnerImageTagActions
+ + +
+ + +
+

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

+
+ +
+ +
+ + + + +
+ + +
+ + {% if showUnlistedContainer %} +

+ {% trans "Unlisted Containers" %} +

+ + + + + + + + + + + + {% for container in unlistedContainers %} + + + + + + {% endfor %} + + +
NameStatusActions
{{container.name}}{{container.status}} + + + +
+ + {% 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." %}

+
+ + + +
+
+

+ {% trans "Images" %} + {% trans "Images" %} + +


+ +
+
+ +
+ +
+
+
+
+ +
+ + + + + + + + + + + + + + + + + + + +
Name (search)TagsAction
+ + + + + + + + {% trans "Pull" %} +
+ + + + + + + + + + + + + {% for name, image in images.items %} + + + + + + + + {% endfor %} + + +
Name (Installed)TagsAction
{{image.name}} + + + + +
+ +
+
+
+ + + +{% 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" %} +

+
+ + +
+ +
+ +
+ +
+
+ +
+ +
+ +
+
+ +
+ +
+ +
+
+ +
+ +
+ +
+
+ + +
+ +
+ +
+
MB
+
+ + {% for port, protocol in portConfig.items %} + +
+ +
+ +
+
+ +
+
to
+
+ +
+
+ + {% endfor %} + + + {% for env, value in envList.items %} + + + + {% endfor %} +
+
+ +
+ +
+ +
+
+ +
+
+ +
+ + +
+ +

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

{$ currentStatus $}

+
+ +
+

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

+
+ +
+

{% trans "Container succesfully created." %}

+
+ + + +
+

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

+
+ + +
+
+ +
+ +
+ +
+
+ + +
+ +
+
+
+ + + +
+ + +{% 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 "Container Information" %} + +

+ + +
+
+ +
+
+
+
+

+ {% trans "Memory Usage" %} +

+
+
+
+
{{ memoryUsage | floatformat:"2" }}%
+
+
+ + +

+ {% trans "CPU Usage" %} +

+
+
+
+
{{ cpuUsage }}%
+
+
+ + + +
+ +
+
+
+ +
+
+
+
+ {% trans "Container ID" %}: {{cid}} +
+ {% trans "Image" %}: {{image}} + + + +
+ {% if ports %} + {% trans "Ports" %}:
+ {% for iport, eport in ports.items %} + {{iport}} {% trans "to" %} {{eport}}
+ {% endfor %} + {% endif %} + +
+ + + + +
+
+
+ +
+
+ + +
+
+ +
+ +
+ +

+ {% trans "Actions" %} +

+ + +
+
+ +
+
+
+
+

Main Actions + +

+ Status: + +
+ + + + +
+
+
+
+ +
+
+
+
+

Other Actions

+ Restart on system reboot:
+ Export file + +
+
+
+
+ +
+ +
+
+ + +
+ +
+ +
+ +

+ {% trans "Logs" %} + +

+ + +
+
+ +
+
+ +
+
+
+ + + + + + + + +
+ +
+ + + +{% 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'), + ), + ]