diff --git a/plogical/DockerSites.py b/plogical/DockerSites.py index f808f755e..9a26e8b42 100644 --- a/plogical/DockerSites.py +++ b/plogical/DockerSites.py @@ -4,19 +4,21 @@ import sys import time -from plogical import randomPassword -from plogical.acl import ACLManager - sys.path.append('/usr/local/CyberCP') import django + +try: + from plogical import randomPassword + from plogical.acl import ACLManager +except: + pass from plogical.processUtilities import ProcessUtilities from plogical.CyberCPLogFileWriter import CyberCPLogFileWriter as logging import argparse import threading as multi -class Docker_Sites(multi.Thread): - +class Docker_Sites(multi.Thread): Wordpress = 1 Joomla = 2 @@ -24,14 +26,16 @@ def __init__(self, function_run, data): multi.Thread.__init__(self) self.function_run = function_run self.data = data - self.JobID = self.data['JobID'] ##JOBID will be file path where status is being written - pass + try: + self.JobID = self.data['JobID'] ##JOBID will be file path where status is being written + except: + pass def run(self): try: if self.function_run == 'DeployWPContainer': self.DeployWPContainer() - elif self.function_run =='SubmitDockersiteCreation': + elif self.function_run == 'SubmitDockersiteCreation': self.SubmitDockersiteCreation() @@ -93,8 +97,8 @@ def SetupHTAccess(port, htaccess): WriteToFile.write(HTAccessContent) WriteToFile.close() - ProcessUtilities.restartLitespeed() - + from plogical.installUtilities import installUtilities + installUtilities.reStartLiteSpeed() # Takes # ComposePath, MySQLPath, MySQLRootPass, MySQLDBName, MySQLDBNUser, MySQLPassword, CPUsMySQL, MemoryMySQL, @@ -117,131 +121,133 @@ def DeployWPContainer(self): logging.statusWriter(self.JobID, 'Docker is ready to use..,10') -# WPSite = f""" -# version: "3.8" -# -# services: -# db: -# image: mysql:5.7 -# restart: always -# volumes: -# - "{self.data['MySQLPath']}:/var/lib/mysql" -# environment: -# MYSQL_ROOT_PASSWORD: {self.data['MySQLRootPass']} -# MYSQL_DATABASE: {self.data['MySQLDBName']} -# MYSQL_USER: {self.data['MySQLDBNUser']} -# MYSQL_PASSWORD: {self.data['MySQLPassword']} -# deploy: -# resources: -# limits: -# cpus: '{self.data['CPUsMySQL']}' # Use 50% of one CPU core -# memory: {self.data['MemoryMySQL']}M # Limit memory to 512 megabytes -# wordpress: -# depends_on: -# - db -# image: wordpress:latest -# restart: always -# ports: -# - "{self.data['port']}:80" -# environment: -# WORDPRESS_DB_HOST: db:3306 -# WORDPRESS_DB_USER: {self.data['MySQLDBNUser']} -# WORDPRESS_DB_PASSWORD: {self.data['MySQLPassword']} -# WORDPRESS_DB_NAME: {self.data['MySQLDBName']} -# volumes: -# - "{self.data['SitePath']}:/var/www/html" -# deploy: -# resources: -# limits: -# cpus: '{self.data['CPUsSite']}' # Use 50% of one CPU core -# memory: {self.data['MemorySite']}M # Limit memory to 512 megabytes -# -# volumes: -# mysql: {{}} -# """ -# -# WPSite = f""" -# # Copyright VMware, Inc. -# # SPDX-License-Identifier: APACHE-2.0 -# -# version: '2' -# services: -# mariadb: -# image: mariadb:10.5.9 -# user: root -# command: --max_allowed_packet=256M -# volumes: -# - "{self.data['MySQLPath']}:/var/lib/mysql:delegated" -# environment: -# - ALLOW_EMPTY_PASSWORD=no -# - MYSQL_USER={self.data['MySQLDBNUser']} -# - MYSQL_PASSWORD={self.data['MySQLPassword']} -# - MYSQL_DATABASE={self.data['MySQLDBName']} -# - MYSQL_ROOT_PASSWORD={self.data['MySQLPassword']} -# deploy: -# resources: -# limits: -# cpus: '{self.data['CPUsMySQL']}' # Use 50% of one CPU core -# memory: {self.data['MemoryMySQL']}M # Limit memory to 512 megabytes -# wordpress: -# image: litespeedtech/openlitespeed:latest -# user: root -# ports: -# - "{self.data['port']}:80" -# # - '443:8443' -# volumes: -# - {self.data['docRoot']}/lsws/conf:/usr/local/lsws/conf -# - {self.data['docRoot']}/lsws/admin-conf:/usr/local/lsws/admin/conf -# - {self.data['docRoot']}/bin:/usr/local/bin -# - {self.data['SitePath']}:/var/www/vhosts/ -# - {self.data['docRoot']}/acme:/root/.acme.sh/ -# - {self.data['docRoot']}/logs:/usr/local/lsws/logs/ -# depends_on: -# - mariadb -# environment: -# - TZ=America/New_York -# - PHP_VERSION=lsphp82 -# - MYSQL_ROOT_PASSWORD={self.data['MySQLPassword']} -# - DOMAIN={self.data['finalURL']} -# - MYSQL_USER={self.data['MySQLDBNUser']} -# - MYSQL_DATABASE={self.data['MySQLDBName']} -# - MYSQL_PASSWORD={self.data['MySQLPassword']} -# # - ALLOW_EMPTY_PASSWORD=no -# # - WORDPRESS_DATABASE_HOST=mariadb -# # - WORDPRESS_DATABASE_PORT_NUMBER=3306 -# # - WORDPRESS_USERNAME={self.data['adminUser']} -# # - WORDPRESS_PASSWORD={self.data["adminPassword"]} -# # - WORDPRESS_EMAIL={self.data["adminEmail"]} -# # - WORDPRESS_BLOG_NAME={self.data["blogTitle"]} -# # - WORDPRESS_ENABLE_REVERSE_PROXY=yes -# deploy: -# resources: -# limits: -# cpus: '{self.data['CPUsSite']}' # Use 50% of one CPU core -# memory: {self.data['MemorySite']}M # Limit memory to 512 megabytes -# # phpmyadmin: -# # image: bitnami/phpmyadmin:latest -# # ports: -# # # - 8080:8080 -# # # - 8443:8443 -# # environment: -# # DATABASE_HOST: mysql -# # restart: always -# # networks: -# # - default -# -# volumes: -# mariadb_data: -# driver: local -# wordpress_data: -# driver: local -# """ + # WPSite = f""" + # version: "3.8" + # + # services: + # db: + # image: mysql:5.7 + # restart: always + # volumes: + # - "{self.data['MySQLPath']}:/var/lib/mysql" + # environment: + # MYSQL_ROOT_PASSWORD: {self.data['MySQLRootPass']} + # MYSQL_DATABASE: {self.data['MySQLDBName']} + # MYSQL_USER: {self.data['MySQLDBNUser']} + # MYSQL_PASSWORD: {self.data['MySQLPassword']} + # deploy: + # resources: + # limits: + # cpus: '{self.data['CPUsMySQL']}' # Use 50% of one CPU core + # memory: {self.data['MemoryMySQL']}M # Limit memory to 512 megabytes + # wordpress: + # depends_on: + # - db + # image: wordpress:latest + # restart: always + # ports: + # - "{self.data['port']}:80" + # environment: + # WORDPRESS_DB_HOST: db:3306 + # WORDPRESS_DB_USER: {self.data['MySQLDBNUser']} + # WORDPRESS_DB_PASSWORD: {self.data['MySQLPassword']} + # WORDPRESS_DB_NAME: {self.data['MySQLDBName']} + # volumes: + # - "{self.data['SitePath']}:/var/www/html" + # deploy: + # resources: + # limits: + # cpus: '{self.data['CPUsSite']}' # Use 50% of one CPU core + # memory: {self.data['MemorySite']}M # Limit memory to 512 megabytes + # + # volumes: + # mysql: {{}} + # """ + # + # WPSite = f""" + # # Copyright VMware, Inc. + # # SPDX-License-Identifier: APACHE-2.0 + # + # version: '2' + # services: + # mariadb: + # image: mariadb:10.5.9 + # user: root + # command: --max_allowed_packet=256M + # volumes: + # - "{self.data['MySQLPath']}:/var/lib/mysql:delegated" + # environment: + # - ALLOW_EMPTY_PASSWORD=no + # - MYSQL_USER={self.data['MySQLDBNUser']} + # - MYSQL_PASSWORD={self.data['MySQLPassword']} + # - MYSQL_DATABASE={self.data['MySQLDBName']} + # - MYSQL_ROOT_PASSWORD={self.data['MySQLPassword']} + # deploy: + # resources: + # limits: + # cpus: '{self.data['CPUsMySQL']}' # Use 50% of one CPU core + # memory: {self.data['MemoryMySQL']}M # Limit memory to 512 megabytes + # wordpress: + # image: litespeedtech/openlitespeed:latest + # user: root + # ports: + # - "{self.data['port']}:80" + # # - '443:8443' + # volumes: + # - {self.data['docRoot']}/lsws/conf:/usr/local/lsws/conf + # - {self.data['docRoot']}/lsws/admin-conf:/usr/local/lsws/admin/conf + # - {self.data['docRoot']}/bin:/usr/local/bin + # - {self.data['SitePath']}:/var/www/vhosts/ + # - {self.data['docRoot']}/acme:/root/.acme.sh/ + # - {self.data['docRoot']}/logs:/usr/local/lsws/logs/ + # depends_on: + # - mariadb + # environment: + # - TZ=America/New_York + # - PHP_VERSION=lsphp82 + # - MYSQL_ROOT_PASSWORD={self.data['MySQLPassword']} + # - DOMAIN={self.data['finalURL']} + # - MYSQL_USER={self.data['MySQLDBNUser']} + # - MYSQL_DATABASE={self.data['MySQLDBName']} + # - MYSQL_PASSWORD={self.data['MySQLPassword']} + # # - ALLOW_EMPTY_PASSWORD=no + # # - WORDPRESS_DATABASE_HOST=mariadb + # # - WORDPRESS_DATABASE_PORT_NUMBER=3306 + # # - WORDPRESS_USERNAME={self.data['adminUser']} + # # - WORDPRESS_PASSWORD={self.data["adminPassword"]} + # # - WORDPRESS_EMAIL={self.data["adminEmail"]} + # # - WORDPRESS_BLOG_NAME={self.data["blogTitle"]} + # # - WORDPRESS_ENABLE_REVERSE_PROXY=yes + # deploy: + # resources: + # limits: + # cpus: '{self.data['CPUsSite']}' # Use 50% of one CPU core + # memory: {self.data['MemorySite']}M # Limit memory to 512 megabytes + # # phpmyadmin: + # # image: bitnami/phpmyadmin:latest + # # ports: + # # # - 8080:8080 + # # # - 8443:8443 + # # environment: + # # DATABASE_HOST: mysql + # # restart: always + # # networks: + # # - default + # + # volumes: + # mariadb_data: + # driver: local + # wordpress_data: + # driver: local + # """ + + self.data['ServiceName'] = self.data["SiteName"].replace(' ', '-') WPSite = f''' version: '3.8' services: - wordpress: + '{self.data['ServiceName']}': user: root image: cyberpanel/openlitespeed:latest ports: @@ -255,19 +261,19 @@ def DeployWPContainer(self): WP_ADMIN_USER: "{self.data['adminUser']}" WP_ADMIN_PASSWORD: "{self.data['adminPassword']}" WP_URL: {self.data['finalURL']} - DB_Host: mariadb:3306 + DB_Host: '{self.data['ServiceName']}-db:3306' SITE_NAME: '{self.data['SiteName']}' volumes: # - "/home/docker/{self.data['finalURL']}:/usr/local/lsws/Example/html" - "/home/docker/{self.data['finalURL']}/data:/usr/local/lsws/Example/html" depends_on: - - mariadb + - '{self.data['ServiceName']}-db' deploy: resources: limits: cpus: '{self.data['CPUsSite']}' # Use 50% of one CPU core memory: {self.data['MemorySite']}M # Limit memory to 512 megabytes - mariadb: + '{self.data['ServiceName']}-db': image: mariadb restart: always environment: @@ -292,8 +298,7 @@ def DeployWPContainer(self): TempCompose = f'/home/cyberpanel/{self.data["finalURL"]}-docker-compose.yml' - - WriteToFile = open(self.data['ComposePath'], 'w') + WriteToFile = open(TempCompose, 'w') WriteToFile.write(WPSite) WriteToFile.close() @@ -311,7 +316,6 @@ def DeployWPContainer(self): if os.path.exists(ProcessUtilities.debugPath): logging.writeToFile(result) - ### Set up Proxy execPath = "/usr/local/CyberCP/bin/python /usr/local/CyberCP/plogical/DockerSites.py" @@ -339,8 +343,6 @@ def DeployWPContainer(self): # # self.ContainerID = stdout.rstrip('\n') - - # command = f'docker-compose -f {self.data["ComposePath"]} exec {self.ContainerID} curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar' # result = ProcessUtilities.outputExecutioner(command) # @@ -367,6 +369,7 @@ def DeployWPContainer(self): except BaseException as msg: logging.writeToFile(f'{str(msg)}. [DeployWPContainer]') + logging.statusWriter(self.JobID, f'Error {str(msg)} . [404]') print(str(msg)) pass @@ -376,7 +379,6 @@ def SubmitDockersiteCreation(self): from websiteFunctions.models import DockerSites, Websites from websiteFunctions.website import WebsiteManager - tempStatusPath = self.data['JobID'] statusFile = open(tempStatusPath, 'w') statusFile.writelines('Creating Website...,10') @@ -395,10 +397,8 @@ def SubmitDockersiteCreation(self): WPpasswd = self.data['WPpasswd'] externalApp = self.data['externalApp'] - currentTemp = tempStatusPath - DataToPass = {} DataToPass['tempStatusPath'] = tempStatusPath DataToPass['domainName'] = Domain @@ -413,50 +413,62 @@ def SubmitDockersiteCreation(self): DataToPass['apacheBackend'] = 0 UserID = userID - try: - website = Websites.objects.get(domain=DataToPass['domainName']) + if Websites.objects.filter(domain=DataToPass['domainName']).count() == 0: + try: + website = Websites.objects.get(domain=DataToPass['domainName']) - if website.phpSelection == 'PHP 7.3': - website.phpSelection = 'PHP 8.0' - website.save() + if website.phpSelection == 'PHP 7.3': + website.phpSelection = 'PHP 8.0' + website.save() + + if ACLManager.checkOwnership(website.domain, self.data['adminID'], + self.data['currentACL']) == 0: + statusFile = open(tempStatusPath, 'w') + statusFile.writelines('You dont own this site.[404]') + statusFile.close() + except: + + ab = WebsiteManager() + coreResult = ab.submitWebsiteCreation(UserID, DataToPass) + coreResult1 = json.loads((coreResult).content) + logging.writeToFile("Creating website result....%s" % coreResult1) + reutrntempath = coreResult1['tempStatusPath'] + while (1): + lastLine = open(reutrntempath, 'r').read() + logging.writeToFile("Error web creating lastline ....... %s" % lastLine) + if lastLine.find('[200]') > -1: + break + elif lastLine.find('[404]') > -1: + statusFile = open(currentTemp, 'w') + statusFile.writelines('Failed to Create Website: error: %s. [404]' % lastLine) + statusFile.close() + return 0 + else: + statusFile = open(currentTemp, 'w') + statusFile.writelines('Creating Website....,20') + statusFile.close() + time.sleep(2) - if ACLManager.checkOwnership(website.domain, self.data['adminID'], - self.data['currentACL']) == 0: statusFile = open(tempStatusPath, 'w') - statusFile.writelines('You dont own this site.[404]') + statusFile.writelines('Creating DockerSite....,30') statusFile.close() - except: - - ab = WebsiteManager() - coreResult = ab.submitWebsiteCreation(UserID, DataToPass) - coreResult1 = json.loads((coreResult).content) - logging.writeToFile("Creating website result....%s" % coreResult1) - reutrntempath = coreResult1['tempStatusPath'] - while (1): - lastLine = open(reutrntempath, 'r').read() - logging.writeToFile("Error web creating lastline ....... %s" % lastLine) - if lastLine.find('[200]') > -1: - break - elif lastLine.find('[404]') > -1: - statusFile = open(currentTemp, 'w') - statusFile.writelines('Failed to Create Website: error: %s. [404]' % lastLine) - statusFile.close() - return 0 - else: - statusFile = open(currentTemp, 'w') - statusFile.writelines('Creating Website....,20') - statusFile.close() - time.sleep(2) - statusFile = open(tempStatusPath, 'w') - statusFile.writelines('Creating DockerSite....,30') - statusFile.close() + webobj = Websites.objects.get(domain=Domain) + if webobj.dockersites_set.all().count() > 0: + logging.statusWriter(self.JobID, f'Docker container already exists on this domain. [404]') + return 0 dbname = randomPassword.generate_pass() dbpasswd = randomPassword.generate_pass() dbusername = randomPassword.generate_pass() MySQLRootPass = randomPassword.generate_pass() + + if DockerSites.objects.count() == 0: + port = '11000' + else: + port = str(int(DockerSites.objects.last().port) + 1) + f_data = { "JobID": tempStatusPath, "ComposePath": f"/home/docker/{Domain}/docker-compose.yml", @@ -467,7 +479,7 @@ def SubmitDockersiteCreation(self): "MySQLPassword": dbpasswd, "CPUsMySQL": MysqlCPU, "MemoryMySQL": MYsqlRam, - "port": '8000', + "port": port, "SitePath": f'/home/{Domain}/public_html/wpdocker', "CPUsSite": SiteCPU, "MemorySite": SiteRam, @@ -478,15 +490,17 @@ def SubmitDockersiteCreation(self): "adminPassword": WPpasswd, "adminEmail": WPemal, "htaccessPath": f'/home/{Domain}/public_html/.htaccess', - "externalApp": externalApp, + "externalApp": webobj.externalApp, "docRoot": f"/home/{Domain}" } - webobj = Websites.objects.get(domain=Domain) + dockersiteobj = DockerSites( - admin = webobj, ComposePath=f"/home/{Domain}/docker-compose.yml", SitePath= f'/home/{Domain}/public_html/wpdocker', + admin=webobj, ComposePath=f"/home/{Domain}/docker-compose.yml", + SitePath=f'/home/{Domain}/public_html/wpdocker', MySQLPath=f'/home/{Domain}/public_html/sqldocker', SiteType=Docker_Sites.Wordpress, MySQLDBName=dbname, - MySQLDBNUser=dbusername, CPUsMySQL=MysqlCPU, MemoryMySQL=MYsqlRam, port=8000, CPUsSite=SiteCPU, MemorySite=SiteRam, - SiteName=sitename, finalURL= Domain, blogTitle=sitename, adminUser=WPusername, adminEmail=WPemal + MySQLDBNUser=dbusername, CPUsMySQL=MysqlCPU, MemoryMySQL=MYsqlRam, port=port, CPUsSite=SiteCPU, + MemorySite=SiteRam, + SiteName=sitename, finalURL=Domain, blogTitle=sitename, adminUser=WPusername, adminEmail=WPemal ) dockersiteobj.save() @@ -497,15 +511,96 @@ def SubmitDockersiteCreation(self): logging.writeToFile("Error Submit Docker site Creation ....... %s" % str(msg)) return 0 + def DeleteDockerApp(self): + try: + + command = f'docker-compose -f /home/docker/{self.data["domain"]}/docker-compose.yml down' + ProcessUtilities.executioner(command) + + command = f'rm -rf /home/docker/{self.data["domain"]}' + ProcessUtilities.executioner(command) + + command = f'rm -f /home/{self.data["domain"]}/public_html/.htaccess' + ProcessUtilities.executioner(command) + + from plogical.installUtilities import installUtilities + installUtilities.reStartLiteSpeed() + + except BaseException as msg: + logging.writeToFile("Error Delete Docker APP ....... %s" % str(msg)) + return 0 + + ## This function need site name which was passed while creating the app + def ListContainers(self): + try: + + import docker + + # Create a Docker client + client = docker.from_env() + + # Define the label to filter containers + label_filter = {'name': self.data['name']} + + # List containers matching the label filter + containers = client.containers.list(filters=label_filter) + + json_data = "[" + checker = 0 + + for container in containers: + + dic = { + 'id': container.short_id, + 'name': container.name, + 'status': container.status, + 'volumes': container.attrs['HostConfig']['Binds'] if 'HostConfig' in container.attrs else [], + 'logs_50': container.logs(tail=50).decode('utf-8'), + 'ports': container.attrs['HostConfig']['PortBindings'] if 'HostConfig' in container.attrs else {} + } + + 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 1, json_data + + except BaseException as msg: + logging.writeToFile("List Container ....... %s" % str(msg)) + return 0, str(msg) + + ### pass container id and number of lines to fetch from logs + def ContainerLogs(self): + try: + import docker + # Create a Docker client + client = docker.from_env() + + # Get the container by ID + container = client.containers.get(self.data['containerID']) + + # Fetch last 'tail' logs for the container + logs = container.logs(tail=self.data['numberOfLines']).decode('utf-8') + + return 1, logs + except BaseException as msg: + logging.writeToFile("List Container ....... %s" % str(msg)) + return 0, str(msg) + + def Main(): try: - parser = argparse.ArgumentParser(description='CyberPanel Docker Sites') parser.add_argument('function', help='Specify a function to call!') parser.add_argument('--port', help='') parser.add_argument('--htaccess', help='') parser.add_argument('--externalApp', help='') + parser.add_argument('--domain', help='') args = parser.parse_args() @@ -545,10 +640,17 @@ def Main(): ds = Docker_Sites('', data) ds.DeployWPContainer() + elif args.function == 'DeleteDockerApp': + data = { + "domain": args.domain} + ds = Docker_Sites('', data) + ds.DeleteDockerApp() + except BaseException as msg: print(str(msg)) pass + if __name__ == "__main__": - Main() \ No newline at end of file + Main() diff --git a/plogical/test.py b/plogical/test.py index 326ae7668..19919d85d 100644 --- a/plogical/test.py +++ b/plogical/test.py @@ -1,21 +1,28 @@ -import re +import docker +# Create a Docker client +client = docker.from_env() -def extract_domain_parts(domain): - # Use a regular expression to extract the domain parts - pattern = r'(?:\w+\.)?(\w+)\.(\w+)' - match = re.match(pattern, domain) +# Define the label to filter containers +label_filter = {'name': 'cyberplanner-new'} - if match: - subdomain = match.group(1) - top_level_domain = match.group(2) - return subdomain, top_level_domain - else: - return None, None +# List containers matching the label filter +containers = client.containers.list(filters=label_filter) +# Print container information +for container in containers: + print(f"Container ID: {container.id}, Name: {container.name}, Status: {container.status}") -# Example usage -domain = "sub.example.ae" -subdomain, top_level_domain = extract_domain_parts(domain) -print("Subdomain:", subdomain) -print("Top-Level Domain:", top_level_domain) + # Get volume information for the container + volumes = container.attrs['HostConfig']['Binds'] if 'HostConfig' in container.attrs else [] + for volume in volumes: + print(f"Volume: {volume}") + + # # Fetch last 50 logs for the container + # logs = container.logs(tail=50).decode('utf-8') + # print(f"Last 50 Logs:\n{logs}") + + # Get exposed ports for the container + ports = container.attrs['HostConfig']['PortBindings'] if 'HostConfig' in container.attrs else {} + for port in ports: + print(f"Exposed Port: {port}")