2025-08-01 14:56:30 +05:00
|
|
|
#!/usr/local/CyberCP/bin/python
|
|
|
|
|
|
|
|
|
|
import os.path
|
|
|
|
|
import sys
|
|
|
|
|
import django
|
|
|
|
|
from datetime import datetime
|
|
|
|
|
|
|
|
|
|
from plogical.DockerSites import Docker_Sites
|
|
|
|
|
|
|
|
|
|
sys.path.append('/usr/local/CyberCP')
|
|
|
|
|
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "CyberCP.settings")
|
|
|
|
|
django.setup()
|
|
|
|
|
import json
|
|
|
|
|
from plogical.acl import ACLManager
|
|
|
|
|
import plogical.CyberCPLogFileWriter as logging
|
|
|
|
|
from django.shortcuts import HttpResponse, render, redirect
|
|
|
|
|
from loginSystem.models import Administrator
|
|
|
|
|
import subprocess
|
|
|
|
|
import shlex
|
|
|
|
|
import time
|
|
|
|
|
from dockerManager.models import Containers
|
|
|
|
|
from math import ceil
|
|
|
|
|
import docker
|
|
|
|
|
import docker.utils
|
|
|
|
|
import requests
|
|
|
|
|
from plogical.processUtilities import ProcessUtilities
|
|
|
|
|
from serverStatus.serverStatusUtil import ServerStatusUtil
|
|
|
|
|
import threading as multi
|
|
|
|
|
from plogical.httpProc import httpProc
|
|
|
|
|
|
|
|
|
|
# Use default socket to connect
|
|
|
|
|
class ContainerManager(multi.Thread):
|
|
|
|
|
|
|
|
|
|
def __init__(self, name=None, function=None, request = None, templateName = None, data = None):
|
|
|
|
|
multi.Thread.__init__(self)
|
|
|
|
|
self.name = name
|
|
|
|
|
self.function = function
|
|
|
|
|
self.request = request
|
|
|
|
|
self.templateName = templateName
|
|
|
|
|
self.data = data
|
|
|
|
|
|
|
|
|
|
def renderDM(self):
|
|
|
|
|
proc = httpProc(self.request, self.templateName, self.data, 'admin')
|
|
|
|
|
return proc.render()
|
|
|
|
|
|
|
|
|
|
def run(self):
|
|
|
|
|
try:
|
|
|
|
|
if self.function == 'submitInstallDocker':
|
|
|
|
|
self.submitInstallDocker()
|
|
|
|
|
elif self.function == 'restartGunicorn':
|
|
|
|
|
command = 'sudo systemctl restart gunicorn.socket'
|
|
|
|
|
ProcessUtilities.executioner(command)
|
|
|
|
|
except BaseException as msg:
|
|
|
|
|
logging.CyberCPLogFileWriter.writeToFile( str(msg) + ' [ContainerManager.run]')
|
|
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
|
def executioner(command, statusFile):
|
|
|
|
|
try:
|
|
|
|
|
res = subprocess.call(shlex.split(command), stdout=statusFile, stderr=statusFile)
|
|
|
|
|
if res == 1:
|
|
|
|
|
return 0
|
|
|
|
|
else:
|
|
|
|
|
return 1
|
|
|
|
|
except BaseException as msg:
|
|
|
|
|
logging.CyberCPLogFileWriter.writeToFile(str(msg))
|
|
|
|
|
return 0
|
|
|
|
|
|
|
|
|
|
def submitInstallDocker(self):
|
|
|
|
|
try:
|
|
|
|
|
currentACL = ACLManager.loadedACL(self.name)
|
|
|
|
|
|
|
|
|
|
if ACLManager.currentContextPermission(currentACL, 'createContainer') == 0:
|
|
|
|
|
return ACLManager.loadError()
|
|
|
|
|
|
|
|
|
|
writeToFile = open(ServerStatusUtil.lswsInstallStatusPath, 'w')
|
|
|
|
|
writeToFile.close()
|
|
|
|
|
|
|
|
|
|
execPath = "/usr/local/CyberCP/bin/python /usr/local/CyberCP/dockerManager/dockerInstall.py"
|
|
|
|
|
ProcessUtilities.executioner(execPath)
|
|
|
|
|
|
|
|
|
|
time.sleep(2)
|
|
|
|
|
|
|
|
|
|
except BaseException as msg:
|
|
|
|
|
logging.CyberCPLogFileWriter.statusWriter(ServerStatusUtil.lswsInstallStatusPath, str(msg) + ' [404].', 1)
|
|
|
|
|
|
|
|
|
|
def createContainer(self, request=None, userID=None, data=None):
|
|
|
|
|
client = docker.from_env()
|
|
|
|
|
dockerAPI = docker.APIClient()
|
|
|
|
|
|
|
|
|
|
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)
|
|
|
|
|
proc = httpProc(request, 'dockerManager/images.html', {"type": admin.type,
|
|
|
|
|
'image': image,
|
|
|
|
|
'tag': tag})
|
|
|
|
|
return proc.render()
|
|
|
|
|
|
|
|
|
|
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]
|
|
|
|
|
|
|
|
|
|
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}
|
|
|
|
|
|
|
|
|
|
template = 'dockerManager/runContainer.html'
|
|
|
|
|
proc = httpProc(request, template, Data, 'admin')
|
|
|
|
|
return proc.render()
|
|
|
|
|
|
|
|
|
|
def loadContainerHome(self, request=None, userID=None, data=None):
|
|
|
|
|
try:
|
|
|
|
|
name = self.name
|
|
|
|
|
|
|
|
|
|
# Check if user is admin or has container access
|
|
|
|
|
currentACL = ACLManager.loadedACL(userID)
|
|
|
|
|
if currentACL['admin'] != 1:
|
|
|
|
|
# For non-admin users, check container ownership
|
|
|
|
|
if ACLManager.checkContainerOwnership(name, userID) != 1:
|
|
|
|
|
return ACLManager.loadError()
|
|
|
|
|
# Admin users can access any container, including ones not in database
|
|
|
|
|
|
|
|
|
|
client = docker.from_env()
|
|
|
|
|
dockerAPI = docker.APIClient()
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
container = client.containers.get(name)
|
|
|
|
|
except docker.errors.NotFound as err:
|
|
|
|
|
return HttpResponse("Container not found")
|
|
|
|
|
|
|
|
|
|
data = {}
|
|
|
|
|
try:
|
|
|
|
|
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)
|
|
|
|
|
data['volList'] = json.loads(con.volumes)
|
|
|
|
|
data['memoryLimit'] = con.memory
|
|
|
|
|
if con.startOnReboot == 1:
|
|
|
|
|
data['startOnReboot'] = 'true'
|
|
|
|
|
data['restartPolicy'] = "Yes"
|
|
|
|
|
else:
|
|
|
|
|
data['startOnReboot'] = 'false'
|
|
|
|
|
data['restartPolicy'] = "No"
|
|
|
|
|
except Containers.DoesNotExist:
|
|
|
|
|
# Container exists in Docker but not in database
|
|
|
|
|
data['name'] = name
|
|
|
|
|
data['image'] = container.image.tags[0] if container.image.tags else "Unknown"
|
|
|
|
|
data['ports'] = {}
|
|
|
|
|
data['cid'] = container.id
|
|
|
|
|
data['envList'] = {}
|
|
|
|
|
data['volList'] = {}
|
|
|
|
|
data['memoryLimit'] = 512
|
|
|
|
|
data['startOnReboot'] = 'false'
|
|
|
|
|
data['restartPolicy'] = "No"
|
|
|
|
|
|
|
|
|
|
stats = container.stats(decode=False, stream=False)
|
|
|
|
|
logs = container.logs(stream=True)
|
|
|
|
|
|
|
|
|
|
data['status'] = container.status
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
cpu_count = len(stats["cpu_stats"]["cpu_usage"]["percpu_usage"])
|
|
|
|
|
except:
|
|
|
|
|
cpu_count = 0
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
|
|
|
|
template = 'dockerManager/viewContainer.html'
|
|
|
|
|
proc = httpProc(request, template, data, 'admin')
|
|
|
|
|
return proc.render()
|
|
|
|
|
except BaseException as msg:
|
|
|
|
|
return HttpResponse(str(msg))
|
|
|
|
|
|
|
|
|
|
def listContainers(self, request=None, userID=None, data=None):
|
|
|
|
|
client = docker.from_env()
|
|
|
|
|
dockerAPI = docker.APIClient()
|
|
|
|
|
|
|
|
|
|
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('<li><a href="\#"></a></li>')
|
|
|
|
|
else:
|
|
|
|
|
pages = ceil(pages)
|
|
|
|
|
finalPages = int(pages) + 1
|
|
|
|
|
|
|
|
|
|
for i in range(1, finalPages):
|
|
|
|
|
pagination.append('<li><a href="\#">' + str(i) + '</a></li>')
|
|
|
|
|
|
|
|
|
|
template = 'dockerManager/listContainers.html'
|
|
|
|
|
proc = httpProc(request, template, {"pagination": pagination,
|
|
|
|
|
"unlistedContainers": unlistedContainers,
|
|
|
|
|
"adminNames": adminNames,
|
|
|
|
|
"showUnlistedContainer": showUnlistedContainer}, 'admin')
|
|
|
|
|
return proc.render()
|
|
|
|
|
|
|
|
|
|
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)
|
|
|
|
|
|
|
|
|
|
client = docker.from_env()
|
|
|
|
|
dockerAPI = docker.APIClient()
|
|
|
|
|
|
|
|
|
|
container = client.containers.get(name)
|
|
|
|
|
logs = container.logs().decode("utf-8")
|
|
|
|
|
|
|
|
|
|
data_ret = {'containerLogStatus': 1, 'containerLog': logs, 'error_message': "None"}
|
|
|
|
|
json_data = json.dumps(data_ret)
|
|
|
|
|
return HttpResponse(json_data)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
except BaseException as 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:
|
|
|
|
|
|
|
|
|
|
admin = Administrator.objects.get(pk=userID)
|
|
|
|
|
if admin.acl.adminStatus != 1:
|
|
|
|
|
return ACLManager.loadErrorJson('createContainerStatus', 0)
|
|
|
|
|
|
|
|
|
|
client = docker.from_env()
|
|
|
|
|
dockerAPI = docker.APIClient()
|
|
|
|
|
|
|
|
|
|
name = data['name']
|
|
|
|
|
image = data['image']
|
|
|
|
|
tag = data['tag']
|
|
|
|
|
dockerOwner = data['dockerOwner']
|
|
|
|
|
memory = data['memory']
|
|
|
|
|
envList = data['envList']
|
|
|
|
|
volList = data['volList']
|
|
|
|
|
|
|
|
|
|
inspectImage = dockerAPI.inspect_image(image + ":" + tag)
|
|
|
|
|
portConfig = {}
|
|
|
|
|
|
|
|
|
|
# Formatting envList for usage
|
|
|
|
|
envDict = {}
|
|
|
|
|
for key, value in envList.items():
|
|
|
|
|
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]
|
|
|
|
|
|
|
|
|
|
volumes = {}
|
|
|
|
|
for index, volume in volList.items():
|
|
|
|
|
volumes[volume['src']] = {'bind': volume['dest'],
|
|
|
|
|
'mode': 'rw'}
|
|
|
|
|
|
|
|
|
|
## Create Configurations
|
|
|
|
|
admin = Administrator.objects.get(userName=dockerOwner)
|
|
|
|
|
|
|
|
|
|
containerArgs = {'image': image + ":" + tag,
|
|
|
|
|
'detach': True,
|
|
|
|
|
'name': name,
|
|
|
|
|
'ports': portConfig,
|
|
|
|
|
'publish_all_ports': True,
|
|
|
|
|
'environment': envDict,
|
|
|
|
|
'volumes': volumes}
|
|
|
|
|
|
|
|
|
|
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),
|
|
|
|
|
volumes=json.dumps(volumes),
|
|
|
|
|
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 as 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:
|
|
|
|
|
|
|
|
|
|
admin = Administrator.objects.get(pk=userID)
|
|
|
|
|
if admin.acl.adminStatus != 1:
|
|
|
|
|
return ACLManager.loadErrorJson('installImageStatus', 0)
|
|
|
|
|
|
|
|
|
|
client = docker.from_env()
|
|
|
|
|
dockerAPI = docker.APIClient()
|
|
|
|
|
|
|
|
|
|
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 as 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)
|
|
|
|
|
|
|
|
|
|
client = docker.from_env()
|
|
|
|
|
dockerAPI = docker.APIClient()
|
|
|
|
|
|
|
|
|
|
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 as 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:
|
|
|
|
|
admin = Administrator.objects.get(pk=userID)
|
|
|
|
|
if admin.acl.adminStatus != 1:
|
|
|
|
|
return ACLManager.loadErrorJson('listContainerStatus', 0)
|
|
|
|
|
|
|
|
|
|
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 as msg:
|
|
|
|
|
dic = {'listContainerStatus': 0, 'error_message': str(msg)}
|
|
|
|
|
json_data = json.dumps(dic)
|
|
|
|
|
return HttpResponse(json_data)
|
|
|
|
|
|
|
|
|
|
def findContainersJson(self, currentACL, userID, pageNumber):
|
|
|
|
|
admin = Administrator.objects.get(pk=userID)
|
|
|
|
|
if admin.acl.adminStatus != 1:
|
|
|
|
|
return ACLManager.loadError()
|
|
|
|
|
|
|
|
|
|
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)
|
|
|
|
|
|
|
|
|
|
client = docker.from_env()
|
|
|
|
|
dockerAPI = docker.APIClient()
|
|
|
|
|
|
|
|
|
|
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 as 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)
|
|
|
|
|
|
|
|
|
|
client = docker.from_env()
|
|
|
|
|
dockerAPI = docker.APIClient()
|
|
|
|
|
|
|
|
|
|
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 as 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)
|
|
|
|
|
|
|
|
|
|
client = docker.from_env()
|
|
|
|
|
dockerAPI = docker.APIClient()
|
|
|
|
|
|
|
|
|
|
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 as 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)
|
|
|
|
|
|
|
|
|
|
client = docker.from_env()
|
|
|
|
|
dockerAPI = docker.APIClient()
|
|
|
|
|
|
|
|
|
|
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 as 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
|
|
|
|
|
admin = Administrator.objects.get(pk=userID)
|
|
|
|
|
if admin.acl.adminStatus != 1:
|
|
|
|
|
return ACLManager.loadErrorJson('assignContainerStatus', 0)
|
|
|
|
|
|
|
|
|
|
client = docker.from_env()
|
|
|
|
|
dockerAPI = docker.APIClient()
|
|
|
|
|
|
|
|
|
|
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 as 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:
|
|
|
|
|
admin = Administrator.objects.get(pk=userID)
|
|
|
|
|
if admin.acl.adminStatus != 1:
|
|
|
|
|
return ACLManager.loadErrorJson('searchImageStatus', 0)
|
|
|
|
|
|
|
|
|
|
client = docker.from_env()
|
|
|
|
|
dockerAPI = docker.APIClient()
|
|
|
|
|
|
|
|
|
|
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 as 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:
|
|
|
|
|
admin = Administrator.objects.get(pk=userID)
|
|
|
|
|
|
|
|
|
|
client = docker.from_env()
|
|
|
|
|
dockerAPI = docker.APIClient()
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
imageList = client.images.list()
|
|
|
|
|
except docker.errors.APIError as err:
|
|
|
|
|
return HttpResponse(str(err))
|
|
|
|
|
|
|
|
|
|
images = {}
|
|
|
|
|
names = []
|
|
|
|
|
|
|
|
|
|
for image in imageList:
|
|
|
|
|
try:
|
|
|
|
|
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}
|
|
|
|
|
except:
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
template = 'dockerManager/images.html'
|
|
|
|
|
proc = httpProc(request, template, {"images": images, "test": ''}, 'admin')
|
|
|
|
|
return proc.render()
|
|
|
|
|
|
|
|
|
|
except BaseException as msg:
|
|
|
|
|
return HttpResponse(str(msg))
|
|
|
|
|
|
|
|
|
|
def manageImages(self, request=None, userID=None, data=None):
|
|
|
|
|
try:
|
|
|
|
|
|
|
|
|
|
client = docker.from_env()
|
|
|
|
|
dockerAPI = docker.APIClient()
|
|
|
|
|
|
|
|
|
|
imageList = client.images.list()
|
|
|
|
|
|
|
|
|
|
images = {}
|
|
|
|
|
names = []
|
|
|
|
|
|
|
|
|
|
for image in imageList:
|
|
|
|
|
try:
|
|
|
|
|
name = image.attrs['RepoTags'][0].split(":")[0]
|
|
|
|
|
if name in names:
|
|
|
|
|
images[name]['tags'].extend(image.tags)
|
|
|
|
|
else:
|
|
|
|
|
names.append(name)
|
|
|
|
|
images[name] = {"name": name,
|
|
|
|
|
"tags": image.tags}
|
|
|
|
|
except:
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
template = 'dockerManager/manageImages.html'
|
|
|
|
|
proc = httpProc(request, template, {"images": images}, 'admin')
|
|
|
|
|
return proc.render()
|
|
|
|
|
|
|
|
|
|
except BaseException as msg:
|
|
|
|
|
return HttpResponse(str(msg))
|
|
|
|
|
|
|
|
|
|
def getImageHistory(self, userID=None, data=None):
|
|
|
|
|
try:
|
|
|
|
|
|
|
|
|
|
name = data['name']
|
|
|
|
|
|
|
|
|
|
client = docker.from_env()
|
|
|
|
|
dockerAPI = docker.APIClient()
|
|
|
|
|
|
|
|
|
|
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 as 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:
|
|
|
|
|
admin = Administrator.objects.get(pk=userID)
|
|
|
|
|
|
|
|
|
|
if admin.acl.adminStatus != 1:
|
|
|
|
|
return ACLManager.loadError()
|
|
|
|
|
|
|
|
|
|
client = docker.from_env()
|
|
|
|
|
dockerAPI = docker.APIClient()
|
|
|
|
|
|
|
|
|
|
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 as 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:
|
|
|
|
|
|
|
|
|
|
client = docker.from_env()
|
|
|
|
|
dockerAPI = docker.APIClient()
|
|
|
|
|
|
|
|
|
|
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']
|
|
|
|
|
volumes = data['volumes']
|
|
|
|
|
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
|
|
|
|
|
|
|
|
|
|
containerArgs = {'image': image + ":" + tag,
|
|
|
|
|
'detach': True,
|
|
|
|
|
'name': name,
|
|
|
|
|
'ports': port,
|
|
|
|
|
'environment': env,
|
|
|
|
|
'volumes': volumes,
|
|
|
|
|
'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 as 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)
|
|
|
|
|
|
|
|
|
|
client = docker.from_env()
|
|
|
|
|
dockerAPI = docker.APIClient()
|
|
|
|
|
|
|
|
|
|
memory = data['memory']
|
|
|
|
|
startOnReboot = data['startOnReboot']
|
|
|
|
|
envList = data['envList']
|
|
|
|
|
volList = data['volList']
|
|
|
|
|
|
|
|
|
|
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.items():
|
|
|
|
|
if (value['name'] != '') or (value['value'] != ''):
|
|
|
|
|
envDict[value['name']] = value['value']
|
|
|
|
|
|
|
|
|
|
volumes = {}
|
|
|
|
|
for index, volume in volList.items():
|
|
|
|
|
if volume['src'] == '' or volume['dest'] == '':
|
|
|
|
|
continue
|
|
|
|
|
volumes[volume['src']] = {'bind': volume['dest'],
|
|
|
|
|
'mode': 'rw'}
|
|
|
|
|
# Prepare data for recreate function
|
|
|
|
|
data = {
|
|
|
|
|
'name': name,
|
|
|
|
|
'unlisted': 0,
|
|
|
|
|
'image': con.image,
|
|
|
|
|
'tag': con.tag,
|
|
|
|
|
'env': envDict,
|
|
|
|
|
'ports': json.loads(con.ports),
|
|
|
|
|
'volumes': volumes,
|
|
|
|
|
'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.volumes = json.dumps(volumes)
|
|
|
|
|
con.save()
|
|
|
|
|
|
|
|
|
|
data_ret = {'saveSettingsStatus': 1, 'error_message': 'None'}
|
|
|
|
|
json_data = json.dumps(data_ret)
|
|
|
|
|
return HttpResponse(json_data)
|
|
|
|
|
|
|
|
|
|
except BaseException as 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)
|
|
|
|
|
|
|
|
|
|
client = docker.from_env()
|
|
|
|
|
dockerAPI = docker.APIClient()
|
|
|
|
|
|
|
|
|
|
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),
|
|
|
|
|
'volumes': json.loads(con.volumes),
|
|
|
|
|
# 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 as 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:
|
|
|
|
|
|
|
|
|
|
admin = Administrator.objects.get(pk=userID)
|
|
|
|
|
if admin.acl.adminStatus != 1:
|
|
|
|
|
return ACLManager.loadError()
|
|
|
|
|
|
|
|
|
|
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 as msg:
|
|
|
|
|
data_ret = {'getTagsStatus': 0, 'error_message': str(msg)}
|
|
|
|
|
json_data = json.dumps(data_ret)
|
|
|
|
|
return HttpResponse(json_data)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def getDockersiteList(self, userID=None, data=None):
|
|
|
|
|
try:
|
|
|
|
|
admin = Administrator.objects.get(pk=userID)
|
|
|
|
|
|
|
|
|
|
if admin.acl.adminStatus != 1:
|
|
|
|
|
return ACLManager.loadError()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
name = data['name']
|
|
|
|
|
|
|
|
|
|
passdata = {}
|
|
|
|
|
passdata["JobID"] = None
|
|
|
|
|
passdata['name'] = name
|
|
|
|
|
da = Docker_Sites(None, passdata)
|
|
|
|
|
retdata = da.ListContainers()
|
|
|
|
|
|
|
|
|
|
data_ret = {'status': 1, 'error_message': 'None', 'data':retdata}
|
|
|
|
|
json_data = json.dumps(data_ret)
|
|
|
|
|
return HttpResponse(json_data)
|
|
|
|
|
|
|
|
|
|
except BaseException as 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 getContainerAppinfo(self, userID=None, data=None):
|
|
|
|
|
try:
|
|
|
|
|
admin = Administrator.objects.get(pk=userID)
|
|
|
|
|
|
|
|
|
|
if admin.acl.adminStatus != 1:
|
|
|
|
|
return ACLManager.loadError()
|
|
|
|
|
|
|
|
|
|
name = data['name']
|
|
|
|
|
containerID = data['id']
|
|
|
|
|
|
|
|
|
|
# Create a Docker client
|
|
|
|
|
client = docker.from_env()
|
|
|
|
|
container = client.containers.get(containerID)
|
|
|
|
|
|
|
|
|
|
# Get detailed container info
|
|
|
|
|
container_info = container.attrs
|
|
|
|
|
|
|
|
|
|
# Calculate uptime
|
|
|
|
|
started_at = container_info.get('State', {}).get('StartedAt', '')
|
|
|
|
|
if started_at:
|
|
|
|
|
started_time = datetime.strptime(started_at.split('.')[0], '%Y-%m-%dT%H:%M:%S')
|
|
|
|
|
uptime = datetime.now() - started_time
|
|
|
|
|
uptime_str = str(uptime).split('.')[0] # Format as HH:MM:SS
|
|
|
|
|
else:
|
|
|
|
|
uptime_str = "N/A"
|
|
|
|
|
|
|
|
|
|
# Get container details
|
|
|
|
|
details = {
|
|
|
|
|
'id': container.short_id,
|
|
|
|
|
'name': container.name,
|
|
|
|
|
'status': container.status,
|
|
|
|
|
'created': container_info.get('Created', ''),
|
|
|
|
|
'started_at': started_at,
|
|
|
|
|
'uptime': uptime_str,
|
|
|
|
|
'image': container_info.get('Config', {}).get('Image', ''),
|
|
|
|
|
'ports': container_info.get('NetworkSettings', {}).get('Ports', {}),
|
|
|
|
|
'volumes': container_info.get('Mounts', []),
|
|
|
|
|
'environment': self._mask_sensitive_env(container_info.get('Config', {}).get('Env', [])),
|
|
|
|
|
'memory_usage': container.stats(stream=False)['memory_stats'].get('usage', 0),
|
|
|
|
|
'cpu_usage': container.stats(stream=False)['cpu_stats']['cpu_usage'].get('total_usage', 0)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
data_ret = {'status': 1, 'error_message': 'None', 'data': [1, details]}
|
|
|
|
|
json_data = json.dumps(data_ret)
|
|
|
|
|
return HttpResponse(json_data)
|
|
|
|
|
|
|
|
|
|
except BaseException as msg:
|
|
|
|
|
data_ret = {'status': 0, 'error_message': str(msg)}
|
|
|
|
|
json_data = json.dumps(data_ret)
|
|
|
|
|
return HttpResponse(json_data)
|
|
|
|
|
|
|
|
|
|
def _mask_sensitive_env(self, env_vars):
|
|
|
|
|
"""Helper method to mask sensitive data in environment variables"""
|
|
|
|
|
masked_vars = []
|
|
|
|
|
sensitive_keywords = ['password', 'secret', 'key', 'token', 'auth']
|
|
|
|
|
|
|
|
|
|
for var in env_vars:
|
|
|
|
|
if '=' in var:
|
|
|
|
|
name, value = var.split('=', 1)
|
|
|
|
|
# Check if this is a sensitive variable
|
|
|
|
|
if any(keyword in name.lower() for keyword in sensitive_keywords):
|
|
|
|
|
masked_vars.append(f"{name}=********")
|
|
|
|
|
else:
|
|
|
|
|
masked_vars.append(var)
|
|
|
|
|
else:
|
|
|
|
|
masked_vars.append(var)
|
|
|
|
|
|
|
|
|
|
return masked_vars
|
|
|
|
|
|
|
|
|
|
def getContainerApplog(self, userID=None, data=None):
|
|
|
|
|
try:
|
|
|
|
|
admin = Administrator.objects.get(pk=userID)
|
|
|
|
|
|
|
|
|
|
if admin.acl.adminStatus != 1:
|
|
|
|
|
return ACLManager.loadError()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
name = data['name']
|
|
|
|
|
containerID = data['id']
|
|
|
|
|
|
|
|
|
|
passdata = {}
|
|
|
|
|
passdata["JobID"] = None
|
|
|
|
|
passdata['name'] = name
|
|
|
|
|
passdata['containerID'] = containerID
|
|
|
|
|
passdata['numberOfLines'] = 50
|
|
|
|
|
da = Docker_Sites(None, passdata)
|
|
|
|
|
retdata = da.ContainerLogs()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
data_ret = {'status': 1, 'error_message': 'None', 'data':retdata}
|
|
|
|
|
json_data = json.dumps(data_ret)
|
|
|
|
|
return HttpResponse(json_data)
|
|
|
|
|
|
|
|
|
|
except BaseException as msg:
|
|
|
|
|
data_ret = {'removeImageStatus': 0, 'error_message': str(msg)}
|
|
|
|
|
json_data = json.dumps(data_ret)
|
|
|
|
|
return HttpResponse(json_data)
|
|
|
|
|
|
|
|
|
|
def recreateappcontainer(self, userID=None, data=None):
|
|
|
|
|
try:
|
|
|
|
|
from websiteFunctions.models import DockerSites
|
|
|
|
|
admin = Administrator.objects.get(pk=userID)
|
|
|
|
|
|
|
|
|
|
if admin.acl.adminStatus != 1:
|
|
|
|
|
return ACLManager.loadError()
|
|
|
|
|
|
|
|
|
|
name = data['name']
|
|
|
|
|
WPusername = data['WPusername']
|
|
|
|
|
WPemail = data['WPemail']
|
|
|
|
|
WPpasswd = data['WPpasswd']
|
|
|
|
|
|
|
|
|
|
dockersite = DockerSites.objects.get(SiteName=name)
|
|
|
|
|
|
|
|
|
|
passdata ={}
|
|
|
|
|
data['JobID'] = ''
|
|
|
|
|
data['Domain'] = dockersite.admin.domain
|
|
|
|
|
data['domain'] = dockersite.admin.domain
|
|
|
|
|
data['WPemal'] = WPemail
|
|
|
|
|
data['Owner'] = dockersite.admin.admin.userName
|
|
|
|
|
data['userID'] = userID
|
|
|
|
|
data['MysqlCPU'] = dockersite.CPUsMySQL
|
|
|
|
|
data['MYsqlRam'] = dockersite.MemoryMySQL
|
|
|
|
|
data['SiteCPU'] = dockersite.CPUsSite
|
|
|
|
|
data['SiteRam'] = dockersite.MemorySite
|
|
|
|
|
data['sitename'] = dockersite.SiteName
|
|
|
|
|
data['WPusername'] = WPusername
|
|
|
|
|
data['WPpasswd'] = WPpasswd
|
|
|
|
|
data['externalApp'] = dockersite.admin.externalApp
|
|
|
|
|
|
|
|
|
|
da = Docker_Sites(None, passdata)
|
|
|
|
|
da.RebuildApp()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
data_ret = {'status': 1, 'error_message': 'None',}
|
|
|
|
|
json_data = json.dumps(data_ret)
|
|
|
|
|
return HttpResponse(json_data)
|
|
|
|
|
|
|
|
|
|
except BaseException as msg:
|
|
|
|
|
data_ret = {'removeImageStatus': 0, 'error_message': str(msg)}
|
|
|
|
|
json_data = json.dumps(data_ret)
|
|
|
|
|
return HttpResponse(json_data)
|
|
|
|
|
|
|
|
|
|
def RestartContainerAPP(self, userID=None, data=None):
|
|
|
|
|
try:
|
|
|
|
|
admin = Administrator.objects.get(pk=userID)
|
|
|
|
|
|
|
|
|
|
if admin.acl.adminStatus != 1:
|
|
|
|
|
return ACLManager.loadError()
|
|
|
|
|
|
|
|
|
|
name = data['name']
|
|
|
|
|
containerID = data['id']
|
|
|
|
|
|
|
|
|
|
passdata = {}
|
|
|
|
|
passdata['containerID'] = containerID
|
|
|
|
|
|
|
|
|
|
da = Docker_Sites(None, passdata)
|
|
|
|
|
retdata = da.RestartContainer()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
data_ret = {'status': 1, 'error_message': 'None', 'data':retdata}
|
|
|
|
|
json_data = json.dumps(data_ret)
|
|
|
|
|
return HttpResponse(json_data)
|
|
|
|
|
|
|
|
|
|
except BaseException as msg:
|
|
|
|
|
data_ret = {'removeImageStatus': 0, 'error_message': str(msg)}
|
|
|
|
|
json_data = json.dumps(data_ret)
|
|
|
|
|
return HttpResponse(json_data)
|
|
|
|
|
|
|
|
|
|
def StopContainerAPP(self, userID=None, data=None):
|
|
|
|
|
try:
|
|
|
|
|
admin = Administrator.objects.get(pk=userID)
|
|
|
|
|
|
|
|
|
|
if admin.acl.adminStatus != 1:
|
|
|
|
|
return ACLManager.loadError()
|
|
|
|
|
|
|
|
|
|
name = data['name']
|
|
|
|
|
containerID = data['id']
|
|
|
|
|
|
|
|
|
|
passdata = {}
|
|
|
|
|
passdata['containerID'] = containerID
|
|
|
|
|
|
|
|
|
|
da = Docker_Sites(None, passdata)
|
|
|
|
|
retdata = da.StopContainer()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
data_ret = {'status': 1, 'error_message': 'None', 'data':retdata}
|
|
|
|
|
json_data = json.dumps(data_ret)
|
|
|
|
|
return HttpResponse(json_data)
|
|
|
|
|
|
|
|
|
|
except BaseException as msg:
|
|
|
|
|
data_ret = {'removeImageStatus': 0, 'error_message': str(msg)}
|
|
|
|
|
json_data = json.dumps(data_ret)
|
2025-09-05 01:14:04 +02:00
|
|
|
return HttpResponse(json_data)
|
|
|
|
|
|
|
|
|
|
def executeContainerCommand(self, userID=None, data=None):
|
|
|
|
|
"""
|
|
|
|
|
Execute a command inside a running Docker container
|
|
|
|
|
"""
|
|
|
|
|
try:
|
|
|
|
|
name = data['name']
|
|
|
|
|
command = data['command']
|
|
|
|
|
|
|
|
|
|
# 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('commandStatus', 0)
|
|
|
|
|
|
|
|
|
|
client = docker.from_env()
|
|
|
|
|
dockerAPI = docker.APIClient()
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
container = client.containers.get(name)
|
|
|
|
|
except docker.errors.NotFound as err:
|
|
|
|
|
data_ret = {'commandStatus': 0, 'error_message': 'Container does not exist'}
|
|
|
|
|
json_data = json.dumps(data_ret)
|
|
|
|
|
return HttpResponse(json_data)
|
|
|
|
|
except:
|
|
|
|
|
data_ret = {'commandStatus': 0, 'error_message': 'Unknown error'}
|
|
|
|
|
json_data = json.dumps(data_ret)
|
|
|
|
|
return HttpResponse(json_data)
|
|
|
|
|
|
|
|
|
|
# Check if container is running
|
|
|
|
|
if container.status != 'running':
|
|
|
|
|
data_ret = {'commandStatus': 0, 'error_message': 'Container must be running to execute commands'}
|
|
|
|
|
json_data = json.dumps(data_ret)
|
|
|
|
|
return HttpResponse(json_data)
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
# Execute command in container
|
|
|
|
|
# Split command into parts for proper execution
|
|
|
|
|
import shlex
|
|
|
|
|
command_parts = shlex.split(command)
|
|
|
|
|
|
|
|
|
|
# Execute command with proper shell
|
|
|
|
|
exec_result = container.exec_run(
|
|
|
|
|
command_parts,
|
|
|
|
|
stdout=True,
|
|
|
|
|
stderr=True,
|
|
|
|
|
stdin=False,
|
|
|
|
|
tty=False,
|
|
|
|
|
privileged=False,
|
|
|
|
|
user='',
|
|
|
|
|
detach=False,
|
|
|
|
|
demux=False,
|
|
|
|
|
workdir=None,
|
|
|
|
|
environment=None
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
# Get output and exit code
|
|
|
|
|
output = exec_result.output.decode('utf-8') if exec_result.output else ''
|
|
|
|
|
exit_code = exec_result.exit_code
|
|
|
|
|
|
|
|
|
|
# Format the response
|
|
|
|
|
if exit_code == 0:
|
|
|
|
|
data_ret = {
|
|
|
|
|
'commandStatus': 1,
|
|
|
|
|
'error_message': 'None',
|
|
|
|
|
'output': output,
|
|
|
|
|
'exit_code': exit_code,
|
|
|
|
|
'command': command
|
|
|
|
|
}
|
|
|
|
|
else:
|
|
|
|
|
data_ret = {
|
|
|
|
|
'commandStatus': 1,
|
|
|
|
|
'error_message': 'Command executed with non-zero exit code',
|
|
|
|
|
'output': output,
|
|
|
|
|
'exit_code': exit_code,
|
|
|
|
|
'command': command
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
json_data = json.dumps(data_ret, ensure_ascii=False)
|
|
|
|
|
return HttpResponse(json_data)
|
|
|
|
|
|
|
|
|
|
except docker.errors.APIError as err:
|
|
|
|
|
data_ret = {'commandStatus': 0, 'error_message': f'Docker API error: {str(err)}'}
|
|
|
|
|
json_data = json.dumps(data_ret)
|
|
|
|
|
return HttpResponse(json_data)
|
|
|
|
|
except Exception as err:
|
|
|
|
|
data_ret = {'commandStatus': 0, 'error_message': f'Execution error: {str(err)}'}
|
|
|
|
|
json_data = json.dumps(data_ret)
|
|
|
|
|
return HttpResponse(json_data)
|
|
|
|
|
|
|
|
|
|
except BaseException as msg:
|
|
|
|
|
data_ret = {'commandStatus': 0, 'error_message': str(msg)}
|
|
|
|
|
json_data = json.dumps(data_ret)
|
2025-08-01 14:56:30 +05:00
|
|
|
return HttpResponse(json_data)
|