1160 lines
49 KiB
Python
1160 lines
49 KiB
Python
# coding: utf-8
|
||
# -------------------------------------------------------------------
|
||
# YakPanel
|
||
# -------------------------------------------------------------------
|
||
# Copyright (c) 2015-2099 YakPanel(www.yakpanel.com) All rights reserved.
|
||
# -------------------------------------------------------------------
|
||
# Author: wzz <wzz@yakpanel.com>
|
||
# -------------------------------------------------------------------
|
||
# ------------------------------
|
||
# docker模型 - docker app 基类
|
||
# ------------------------------
|
||
import json
|
||
import os
|
||
import sys
|
||
import time
|
||
from datetime import datetime, timedelta
|
||
|
||
if "/www/server/panel/class" not in sys.path:
|
||
sys.path.insert(0, "/www/server/panel/class")
|
||
|
||
import public
|
||
from mod.project.docker.composeMod import main as composeMod
|
||
|
||
dk_project_path="/www/dk_project"
|
||
project_path_file = "{}/class_v2/btdockerModelV2/config/project_path.pl".format(public.get_panel_path())
|
||
if os.path.exists(project_path_file):
|
||
path = public.readFile(project_path_file)
|
||
if path:
|
||
dk_project_path = path.strip()
|
||
class App(composeMod):
|
||
dk_project_path = dk_project_path
|
||
|
||
def __init__(self):
|
||
super(App, self).__init__()
|
||
self.types = (
|
||
"BuildWebsite",
|
||
"Database",
|
||
"WebServer",
|
||
"RunTime",
|
||
"Tools",
|
||
"AI",
|
||
"Storage",
|
||
"Media",
|
||
"Middleware",
|
||
"DevOps",
|
||
"DevTool",
|
||
"Securtiy",
|
||
"Email",
|
||
"Other",
|
||
)
|
||
self.app_name = None
|
||
self.service_name = None
|
||
self.data = None
|
||
self.app_path = None
|
||
self.service_path = None
|
||
self.plugin_path = None
|
||
self.project_path = os.path.join(self.dk_project_path, "dk_app")
|
||
if not os.path.exists(self.project_path):
|
||
public.ExecShell("mkdir -p {}".format(self.project_path))
|
||
self.ollama_online_models_file = "{}/ollama_online_models.json".format(self.project_path)
|
||
self.templates_path = os.path.join(self.project_path, "templates")
|
||
self.app_template_path = None
|
||
self.delete_pl = False
|
||
self.r_id = False
|
||
self.user_conf_file = None
|
||
self.site_domains = None
|
||
self.compose_file = None
|
||
self.all_ports = []
|
||
self.app_cmd_log = None
|
||
self.up_cmd = None
|
||
self.host_str = "127.0.0.1:"
|
||
self.apps_json_file = os.path.join(self.project_path, "apps.json")
|
||
# self.apps_json_file = os.path.join("/www/server/panel/mod/project/docker/app", "apps.json")
|
||
self.app_json = None
|
||
self.apps_json = None
|
||
self.apps_list = None
|
||
self.app_tags_file = os.path.join(self.project_path, "apptags.json")
|
||
# self.app_tags_file = os.path.join("/www/server/panel/mod/project/docker/app", "apptags.json")
|
||
self.installed_json_file = os.path.join(self.project_path, "installed.json")
|
||
self.installed_app_template = {
|
||
"id": None, # name + appid + appname = md5
|
||
"service_name": None, # unique
|
||
"appid": None,
|
||
"appdesc": None,
|
||
"appname": None,
|
||
"apptitle": None,
|
||
"appstatus": None,
|
||
"apptype": None,
|
||
"canUpdate": None,
|
||
"createat": None,
|
||
"updateat": None,
|
||
"m_version": None,
|
||
"s_version": None,
|
||
"home": None,
|
||
"cpu": 0,
|
||
"mem": 0,
|
||
"disk": 0,
|
||
"path": None,
|
||
"host_ip": "127.0.0.1",
|
||
"port": None,
|
||
"domain": None,
|
||
"icon": None,
|
||
"status": None,
|
||
"version": None,
|
||
"sort": None,
|
||
"installed": True,
|
||
"backup": None,
|
||
"depDataBase": None,
|
||
"appinfo": None,
|
||
}
|
||
self.installed_app = None
|
||
self.app_conf_file = None
|
||
self.app_installed_json = []
|
||
self.app_version = None
|
||
self.plugin_version = None
|
||
self.app_type = None
|
||
self.backup_path = os.path.join(self.dk_project_path, "backup")
|
||
self.apps_backup_path = os.path.join(self.backup_path, "apps")
|
||
self.service_backup_path = None
|
||
self.backup_conf = {
|
||
"backup_type": "local",
|
||
"backup_path": None,
|
||
"backup_time": str,
|
||
"file_name": None,
|
||
"size": int,
|
||
}
|
||
self.backup_json_file = os.path.join(self.backup_path, "backup.json")
|
||
self.app_scripts = None
|
||
def set_up_cmd(self, cmd) -> 'App':
|
||
self.up_cmd = cmd
|
||
return self
|
||
|
||
def set_service_backup_path(self) -> 'App':
|
||
self.service_backup_path = os.path.join(self.apps_backup_path, self.service_name)
|
||
return self
|
||
|
||
def set_app_type(self) -> 'App':
|
||
self.app_type = self.app_json["apptype"]
|
||
return self
|
||
|
||
def set_service_path(self) -> 'App':
|
||
self.service_path = os.path.join(self.app_path, self.service_name)
|
||
return self
|
||
|
||
def set_service_name(self, service_name: str) -> 'App':
|
||
self.service_name = service_name
|
||
return self
|
||
|
||
def set_app_conf_file(self) -> 'App':
|
||
self.app_conf_file = os.path.join(self.service_path, "{}_conf.json".format(self.app_name))
|
||
return self
|
||
|
||
def apply_installed_app_template(self):
|
||
self.installed_app = self.installed_app_template.copy()
|
||
|
||
def set_cmd_log(self) -> 'App':
|
||
self.app_cmd_log = os.path.join("/tmp", "{}.log".format(self.service_name))
|
||
return self
|
||
|
||
def set_app_name(self, app_name: str) -> 'App':
|
||
self.app_name = app_name
|
||
return self
|
||
|
||
def set_compose_file(self) -> 'App':
|
||
self.compose_file = os.path.join(self.service_path, "docker-compose.yml")
|
||
return self
|
||
|
||
def set_site_domains(self, get) -> 'App':
|
||
self.site_domains = get.domain.split('\n')
|
||
return self
|
||
|
||
def set_user_conf_file(self) -> 'App':
|
||
self.user_conf_file = os.path.join(self.service_path, "user_conf.json")
|
||
return self
|
||
|
||
def set_plugin_path(self, app_name: str) -> 'App':
|
||
self.plugin_path = os.path.join(public.get_panel_path(), "plugin", app_name)
|
||
return self
|
||
|
||
def set_app_template_path(self, app_name: str) -> 'App':
|
||
self.app_template_path = os.path.join(self.templates_path, app_name)
|
||
return self
|
||
|
||
def set_app_path(self) -> 'App':
|
||
self.app_path = os.path.join(self.project_path, self.app_name)
|
||
return self
|
||
|
||
def set_data(self, data: str) -> 'App':
|
||
try:
|
||
self.data = json.loads(data)
|
||
return self
|
||
except:
|
||
pass
|
||
|
||
def read_json(self, file):
|
||
try:
|
||
return json.loads(public.readFile(file))
|
||
except:
|
||
return False
|
||
|
||
def write_json(self, file, data):
|
||
try:
|
||
public.writeFile(file, json.dumps(data))
|
||
return True
|
||
except:
|
||
return False
|
||
|
||
def get_installed_json(self) -> 'App':
|
||
'''
|
||
@name 获取已安装的json配置文件信息
|
||
'''
|
||
try:
|
||
installed_json = json.loads(public.readFile(self.installed_json_file))
|
||
for app_type in installed_json.keys():
|
||
if app_type == self.app_type:
|
||
self.app_installed_json = installed_json[app_type]
|
||
return self
|
||
except:
|
||
return self
|
||
|
||
def get_app_json(self) -> 'App':
|
||
try:
|
||
try:
|
||
apps_json = json.loads(public.readFile(self.apps_json_file))
|
||
except:
|
||
apps_json = public.readFile(self.apps_json_file)
|
||
|
||
if not apps_json:
|
||
return self
|
||
|
||
for app in apps_json:
|
||
if app["appname"] == self.app_name:
|
||
self.app_json = app
|
||
return self
|
||
except:
|
||
return self
|
||
|
||
def download_apps_json(self) -> 'App':
|
||
try:
|
||
public.downloadFile(public.get_url() + '/src/dk_app/yakpanel/apps/apps.json', self.apps_json_file)
|
||
|
||
public.downloadFile(public.get_url() + '/src/dk_app/yakpanel/apps/apptags.json', self.app_tags_file)
|
||
return self
|
||
except:
|
||
return self
|
||
|
||
def get_apps_json(self) -> 'App':
|
||
try:
|
||
if not os.path.exists(self.apps_json_file) or not os.path.exists(self.app_tags_file):
|
||
public.ExecShell("rm -f {}".format(self.apps_json_file))
|
||
public.ExecShell("rm -f {}".format(self.app_tags_file))
|
||
self.download_apps_json()
|
||
try:
|
||
apps_json = json.loads(public.readFile(self.apps_json_file))
|
||
except:
|
||
apps_json = public.readFile(self.apps_json_file)
|
||
|
||
if not apps_json:
|
||
return self
|
||
|
||
if type(apps_json) == str:
|
||
try:
|
||
apps_json = json.loads(apps_json)
|
||
except:
|
||
return self
|
||
|
||
self.apps_json = apps_json
|
||
return self
|
||
except:
|
||
return self
|
||
|
||
# 2024/7/29 下午3:33 检查域名是否允许被添加到当前应用
|
||
def check_domain(self):
|
||
if not "DOMAIN" in self.data["install_config@0"] or self.data["install_config@0"]["DOMAIN"] == "":
|
||
return public.return_message(-1, 0, public.lang("The domain name cannot be empty!"))
|
||
|
||
# 2024/2/23 下午 12:05 如果其他地方有这个域名,则禁止添加
|
||
for domain in self.site_domains:
|
||
newpid = public.M('domain').where("name=? and port=?", (domain, 80)).getField('pid')
|
||
if newpid:
|
||
result = public.M('sites').where("id=?", (newpid,)).find()
|
||
if result:
|
||
user_conf = self.read_json(self.user_conf_file)
|
||
if not user_conf:
|
||
return public.return_message(-1, 0, 'Project type [{}] already exists with domain name: {}, please do not add it again!'.format(
|
||
result['project_type'], domain))
|
||
if user_conf.get("install_config@0").get("DOMAIN") != domain:
|
||
return public.return_message(-1, 0, 'Project type [{}] already exists with domain name: {}, please do not add it again!'.format(
|
||
result['project_type'], domain))
|
||
self.delete_pl = True
|
||
self.r_id = result['id']
|
||
break
|
||
|
||
|
||
return public.return_message(0, 0, '')
|
||
|
||
# 2024/7/2 上午10:40 检查wordpress的compose.yml文件是否存在
|
||
def check_yml(self):
|
||
'''
|
||
@name
|
||
@author wzz <2024/7/2 上午10:41>
|
||
@param "data":{"参数名":""} <数据类型> 参数描述
|
||
@return dict{"status":True/False,"msg":"提示信息"}
|
||
'''
|
||
if not os.path.exists(self.service_path):
|
||
os.makedirs(self.service_path, exist_ok=True, mode=0o755)
|
||
|
||
if os.path.exists(os.path.join(self.service_path, "docker-compose.yml")):
|
||
public.ExecShell("rm -f {}".format(os.path.join(self.service_path, "docker-compose.yml")))
|
||
|
||
if os.path.exists(os.path.join(self.service_path, ".env")):
|
||
public.ExecShell("rm -f {}".format(os.path.join(self.service_path, ".env")))
|
||
|
||
if not os.path.exists(os.path.join(self.service_path, "docker-compose.yml")):
|
||
public.ExecShell("\cp -r {}/*.yml {}".format(
|
||
self.app_template_path, self.service_path))
|
||
|
||
if not os.path.exists(os.path.join(self.service_path, ".env")):
|
||
public.ExecShell("\cp -r {}/.env {}".format(
|
||
self.app_template_path, self.service_path))
|
||
|
||
if (not os.path.exists(os.path.join(self.service_path, "docker-compose.yml")) or
|
||
not os.path.exists(os.path.join(self.service_path, ".env"))):
|
||
return False
|
||
return True
|
||
|
||
# 2024/8/15 下午3:54 更新图标
|
||
def update_ico(self):
|
||
'''
|
||
@name 更新图标
|
||
'''
|
||
zip_ico_path = "{}/YakPanel/static/img/soft_ico/".format(public.get_panel_path())
|
||
ico_path = os.path.join(public.get_panel_path(), "YakPanel/static/img/soft_ico/dkapp")
|
||
if os.path.exists(ico_path):
|
||
public.ExecShell("rm -rf {}".format(ico_path))
|
||
tmp_path = os.path.join("/tmp", "dkapp_ico")
|
||
if not os.path.exists(tmp_path):
|
||
public.ExecShell("mkdir -p {}".format(tmp_path))
|
||
|
||
public.downloadFile(public.get_url() + '/src/dk_app/yakpanel/apps/dkapp_ico.zip', os.path.join(tmp_path, "dkapp_ico.zip"))
|
||
public.ExecShell("unzip -o {}/dkapp_ico.zip -d {}".format(tmp_path, zip_ico_path))
|
||
public.ExecShell("cd {} && mv dkapp_ico dkapp".format(zip_ico_path))
|
||
|
||
public.ExecShell("chmod -R 644 {}".format(ico_path))
|
||
public.ExecShell("chown -R root:root {}".format(ico_path))
|
||
public.ExecShell("rm -rf {}".format(tmp_path))
|
||
|
||
# 2024/8/15 下午5:54 检查 yakpanel_net docker 网络(旧版为 baota_net,若存在可手动 docker network connect)
|
||
def check_yakpanel_net(self):
|
||
'''
|
||
@name 检查 yakpanel_net 是否存在
|
||
'''
|
||
stdout, stderr = public.ExecShell("docker network ls | grep yakpanel_net")
|
||
if not stdout:
|
||
stdout, stderr = public.ExecShell("docker network create yakpanel_net")
|
||
if stderr and "setlocale: LC_ALL: cannot change locale (en_US.UTF-8)" not in stderr:
|
||
return public.return_message(-1, 0, public.lang("Failed to create a yakpanel net network. err: {}",stderr))
|
||
return public.return_message(0, 0, '')
|
||
|
||
|
||
# 2024/7/29 下午4:32 检查端口是否被其他进程占用而非本应用
|
||
def check_port(self, get):
|
||
'''
|
||
@name 检查端口是否被其他进程占用而非本应用
|
||
@param "data":{"参数名":""} <数据类型> 参数描述
|
||
@return dict{"status":True/False,"msg":"提示信息"}
|
||
'''
|
||
result_port = int(get.c_port)
|
||
if result_port > 65535 or result_port < 0:
|
||
return public.return_message(-1, 0, public.lang("Port range error, please enter a port between 0-65535!"))
|
||
|
||
import psutil
|
||
for net_port in psutil.net_connections("tcp4"):
|
||
self.all_ports.append(net_port.laddr.port)
|
||
|
||
if int(get.c_port) in self.all_ports:
|
||
get.path = self.compose_file
|
||
compose_ps = self.ps(get)
|
||
is_break = False
|
||
for ps in compose_ps:
|
||
if ps == "":
|
||
continue
|
||
publishers = ps.get("Publishers")
|
||
for pu in publishers:
|
||
if int(get.c_port) == int(pu.get("PublishedPort")):
|
||
is_break = True
|
||
break
|
||
if is_break:
|
||
break
|
||
else:
|
||
from safeModel.firewallModel import main as firewall_main
|
||
get.port = str(get.c_port)
|
||
res_dict = firewall_main().get_listening_processes(get)
|
||
return public.return_message(-1, 0, public.lang("The {} port has been occupied by [{}], please change the port!", get.port, res_dict.get("process_name")))
|
||
|
||
return public.return_message(0, 0, '')
|
||
|
||
# 2024/7/29 下午4:56 启动应用
|
||
def up_app(self):
|
||
'''
|
||
@name
|
||
@author wzz <2024/7/29 下午4:57>
|
||
@param "data":{"参数名":""} <数据类型> 参数描述
|
||
@return dict{"status":True/False,"msg":"提示信息"}
|
||
'''
|
||
import subprocess
|
||
subprocess.Popen(self.up_cmd, shell=True)
|
||
|
||
# 2024/7/29 下午5:03 添加反代
|
||
def create_proxy(self, get):
|
||
'''
|
||
@name 添加反代
|
||
@param "data":{"参数名":""} <数据类型> 参数描述
|
||
@return dict{"status":True/False,"msg":"提示信息"}
|
||
'''
|
||
from mod.project.docker.proxy.base import main as proxyMod
|
||
pMod = proxyMod()
|
||
|
||
try:
|
||
args = public.to_dict_obj({
|
||
"proxy_pass": "http://127.0.0.1:{}".format(get.port_list[0]),
|
||
"proxy_type": "http",
|
||
"domains": get.domain,
|
||
"proxy_host": "$http_host",
|
||
"remark": "Reverse proxy for {}(docker app)".format(self.service_name),
|
||
})
|
||
create_result = pMod.create(args)
|
||
# public.print_log("添加反代 create_result---{}".format(create_result))
|
||
|
||
if not create_result['status']:
|
||
return public.return_message(-1, 0, create_result['msg'])
|
||
except Exception as e:
|
||
return public.return_message(-1, 0, public.lang("Domain name access failed to be added due to the following reasons:{}",str(e)))
|
||
return public.return_message(0, 0, '')
|
||
|
||
# 2024/7/29 下午5:09 检测是否关闭域名访问并且不允许外部访问
|
||
def check_close_domain(self, get):
|
||
'''
|
||
@name 检测是否关闭域名访问并且不允许外部访问
|
||
@param "data":{"参数名":""} <数据类型> 参数描述
|
||
@return dict{"status":True/False,"msg":"提示信息"}
|
||
'''
|
||
if get.disable_domain == 1 and get.allow_access == 1:
|
||
self.host_str = "0.0.0.0:"
|
||
|
||
# 2024/7/30 上午10:17 写入已安装的APP数据为json
|
||
def write_installed_json(self, get):
|
||
'''
|
||
@name 写入已安装的APP数据为json
|
||
@param "data":{"参数名":""} <数据类型> 参数描述
|
||
@return dict{"status":True/False,"msg":"提示信息"}
|
||
'''
|
||
installed_app_id = public.md5(
|
||
self.service_name + str(self.app_json["appid"]) + self.app_json["appname"] + str(int(time.time())))
|
||
self.installed_app["id"] = installed_app_id
|
||
self.installed_app["service_name"] = self.service_name
|
||
self.installed_app["appid"] = self.app_json["appid"]
|
||
self.installed_app["appdesc"] = self.app_json["appdesc"]
|
||
self.installed_app["appname"] = self.app_json["appname"]
|
||
self.installed_app["apptitle"] = self.app_json["apptitle"]
|
||
self.installed_app["appstatus"] = self.app_json["appstatus"]
|
||
self.installed_app["apptype"] = self.app_json["apptype"]
|
||
self.installed_app["canUpdate"] = 0
|
||
self.installed_app["createat"] = int(time.time())
|
||
self.installed_app["updateat"] = self.app_json["updateat"]
|
||
self.installed_app["home"] = self.app_json["home"]
|
||
self.installed_app["cpu"] = self.app_json["cpu"]
|
||
self.installed_app["mem"] = self.app_json["mem"]
|
||
self.installed_app["disk"] = self.app_json["disk"]
|
||
self.installed_app["path"] = self.app_path
|
||
self.installed_app["port"] = get.port_list
|
||
self.installed_app["icon"] = self.app_json["icon"]
|
||
self.installed_app["status"] = None
|
||
self.installed_app["host_ip"] = get.host_ip
|
||
self.installed_app["m_version"] = get.m_version
|
||
self.installed_app["s_version"] = get.s_version
|
||
self.installed_app["version"] = get.version
|
||
self.installed_app["sort"] = self.app_json["sort"]
|
||
self.installed_app["domain"] = get.site_domains[0] if len(get.site_domains) > 0 else None
|
||
self.installed_app["depDataBase"] = {"db": get.app_db, "type": get.depdbtype}
|
||
self.installed_app["depMiddleWare"] = {"db": get.cache_db_host, "type": get.depmidtype}
|
||
self.installed_app["appinfo"] = get.app_info
|
||
|
||
installed_json = self.read_json(self.installed_json_file)
|
||
if installed_json:
|
||
for app_type in installed_json.keys():
|
||
if app_type == self.app_type:
|
||
installed_json[app_type].append(self.installed_app)
|
||
break
|
||
else:
|
||
installed_json[self.app_type] = [self.installed_app]
|
||
else:
|
||
installed_json = {self.app_type: [self.installed_app]}
|
||
|
||
self.write_json(self.installed_json_file, installed_json)
|
||
|
||
# 2024/7/31 上午11:52 校验web项目的传参
|
||
def check_web_params(self, get):
|
||
'''
|
||
@name 参数校验
|
||
@param "data":{"参数名":""} <数据类型> 参数描述
|
||
@return dict{"status":True/False,"msg":"提示信息"}
|
||
'''
|
||
get.domain = get.get("domain", None)
|
||
if get.domain is None:
|
||
return public.return_message(-1, 0, public.lang("Please pass the domain parameter!"))
|
||
|
||
get.disable_domain = get.get("disable_domain", None)
|
||
if get.disable_domain is None:
|
||
return public.return_message(-1, 0, public.lang("Please pass the disable_domain parameter!"))
|
||
|
||
return public.return_message(0, 0, '')
|
||
|
||
# 2024/7/31 上午11:57 校验通用compose配置传参
|
||
def check_compose_params(self, get):
|
||
'''
|
||
@name 参数校验
|
||
@param "data":{"参数名":""} <数据类型> 参数描述
|
||
@return dict{"status":True/False,"msg":"提示信息"}
|
||
'''
|
||
get.app_name = get.get("app_name", None)
|
||
if get.app_name is None:
|
||
return public.return_message(-1, 0, public.lang("Please pass the app_name parameter!"))
|
||
|
||
# get.app_path = get.get("app_path", None)
|
||
# if get.app_path is None:
|
||
# return public.return_message(-1, 0, public.lang("请传app_path参数!"))
|
||
|
||
get.cpus = get.get("cpus", 0)
|
||
get.memory_limit = get.get("memory_limit", 0)
|
||
|
||
get.m_version = get.get("m_version", None)
|
||
if get.m_version is None:
|
||
return public.return_message(-1, 0, public.lang("Please pass the memory_limit parameter!"))
|
||
|
||
get.s_version = get.get("s_version", None)
|
||
get.s_version = get.s_version.strip(".undefined") if get.s_version is not None else None
|
||
if get.s_version is None:
|
||
return public.return_message(-1, 0, public.lang("Please pass the s_version parameter!"))
|
||
|
||
if get.s_version == "" or get.s_version is None:
|
||
if get.m_version == "" or get.m_version is None: get.version = "latest"
|
||
get.version = get.m_version
|
||
else:
|
||
get.version = "{}.{}".format(get.m_version, get.s_version)
|
||
|
||
get.service_name = get.get("service_name", None)
|
||
if get.service_name is None:
|
||
return public.return_message(-1, 0, public.lang("Please pass the service_name parameter!"))
|
||
|
||
get.allow_access = get.get("allow_access", None)
|
||
if get.allow_access is None:
|
||
return public.return_message(-1, 0, public.lang("Please pass the allow_access parameter!"))
|
||
|
||
get.host_ip = "127.0.0.1"
|
||
if int(get.allow_access) == 1:
|
||
get.host_ip = "0.0.0.0"
|
||
|
||
get.domain = get.get("domain", "")
|
||
get.site_domains = get.domain.split("\n") if get.domain != "" else []
|
||
if len(get.site_domains) > 0:
|
||
cwsres = self.check_web_status()
|
||
if not cwsres["status"]: return cwsres
|
||
|
||
get.disable_domain = get.get("disable_domain", 0)
|
||
if int(get.disable_domain) == 0 and self.app_type in ("BuildWebsite", "Storage"):
|
||
if get.domain == "":
|
||
return public.return_message(-1, 0, public.lang("The domain name cannot be empty, or please check the box not to set the domain name!"))
|
||
|
||
return public.return_message(0, 0, True)
|
||
|
||
# 2024/8/1 上午9:45 添加数据库到面板远程数据库管理中
|
||
def apply_database_to_panel(self, get):
|
||
'''
|
||
@name 添加数据库到面板远程数据库管理中
|
||
@param "data":{"参数名":""} <数据类型> 参数描述
|
||
@return dict{"status":True/False,"msg":"提示信息"}
|
||
'''
|
||
# 2024/8/1 上午9:52 因为数据库可能第一时间不会初始化完成,所以先插入数据库服务器信息,弃用导包的方式
|
||
get.db_host = "127.0.0.1"
|
||
get.db_port = get.c_port
|
||
get.db_user = "root"
|
||
if self.app_name == "mysql":
|
||
get.db_password = get.mysql_root_password
|
||
elif self.app_name == "mariadb":
|
||
get.db_password = get.mariadb_root_password
|
||
elif self.app_name == "postgresql":
|
||
get.db_user = get.postgres_user
|
||
get.db_password = get.postgres_password
|
||
get.ps = self.service_name
|
||
get.db_ps = self.service_name
|
||
|
||
if public.M("database_servers").where("db_host=? AND db_port=? AND LOWER(db_type)=LOWER('mysql')",
|
||
(get.db_host, get.db_port)).count():
|
||
return public.returnMsg(False, "The specified server already exists: [{}:{}]".format(get.db_host, get.db_port))
|
||
get.db_port = int(get.db_port)
|
||
pdata = {
|
||
"db_host": get.db_host,
|
||
"db_port": get.db_port,
|
||
"db_user": get.db_user,
|
||
"db_type": get.type,
|
||
"db_password": get.db_password,
|
||
"ps": public.xssencode2(get.db_ps.strip()),
|
||
"addtime": int(time.time())
|
||
}
|
||
|
||
result = public.M("database_servers").insert(pdata)
|
||
|
||
if isinstance(result, int):
|
||
public.WriteLog("Database management", "Add remote {app_name} server [{db_host}:{db_port}]".format(
|
||
app_name=self.app_name, db_host=get.db_host, db_port=get.db_port))
|
||
return public.returnMsg(True, "Successfully added!")
|
||
return public.returnMsg(False, "Add failed: {result}".format(result=result))
|
||
|
||
# 2024/8/1 上午9:55 删除面板远程数据库中的指定数据库
|
||
def delete_database_from_panel(self, get):
|
||
'''
|
||
@name 删除面板远程数据库中的指定数据库
|
||
@param "data":{"参数名":""} <数据类型> 参数描述
|
||
@return dict{"status":True/False,"msg":"提示信息"}
|
||
'''
|
||
from database import database
|
||
db_list = database().GetCloudServer(get)
|
||
for db in db_list:
|
||
if "db_type" not in db:
|
||
continue
|
||
if db["ps"] == self.service_name:
|
||
get.id = db['id']
|
||
database().RemoveCloudServer(get)
|
||
break
|
||
if (db["db_host"] == "127.0.0.1" and db["db_port"] == int(get.c_port) and db["db_type"] == "mysql" and
|
||
db["db_password"] == get.mysql_root_password):
|
||
get.id = db['id']
|
||
database().RemoveCloudServer(get)
|
||
break
|
||
|
||
# 2024/8/21 下午3:56 删除面板pgsql指定远程数据库中的数据库
|
||
def delete_pgsql_database_from_panel(self, get):
|
||
'''
|
||
@name 删除面板pgsql指定远程数据库中的数据库
|
||
'''
|
||
from databaseModelV2.pgsqlModel import main as pgsqlModel
|
||
args = public.dict_obj()
|
||
args.data = {"type": "pgsql"}
|
||
db_list = pgsqlModel().GetCloudServer(args)['message']
|
||
for db in db_list:
|
||
if db["ps"] == self.service_name:
|
||
args.id = db["id"]
|
||
pgsqlModel().RemoveCloudServer(args)
|
||
break
|
||
|
||
# 2024/8/15 下午4:01 删除指定app的数据库
|
||
def delete_database_for_app(self, depDataBase):
|
||
'''
|
||
@name 删除指定app的数据库
|
||
'''
|
||
from database import database
|
||
from datalistModel.dataModel import main as dataModel
|
||
args = public.dict_obj()
|
||
args.search = depDataBase
|
||
args.table = "databases"
|
||
args.p = 1
|
||
args.limit = 20000
|
||
args.db_type = "mysql"
|
||
try:
|
||
db_list = dataModel().get_data_list(args)
|
||
except:
|
||
public.print_log(public.get_error_info())
|
||
|
||
if type(db_list) != dict: return
|
||
|
||
for db in db_list["data"]:
|
||
if db["name"] == depDataBase:
|
||
args.id = db["id"]
|
||
args.name = db["name"]
|
||
database().DeleteDatabase(args)
|
||
break
|
||
|
||
# 2024/8/21 下午3:21 删除指定app的pgsql数据库
|
||
def delete_pgsql_database_for_app(self, depDataBase):
|
||
'''
|
||
@name 删除指定app的pgsql数据库
|
||
'''
|
||
from databaseModelV2.pgsqlModel import main as pgsqlModel
|
||
args = public.dict_obj()
|
||
args.search = depDataBase
|
||
args.table = "databases"
|
||
args.p = 1
|
||
args.limit = 20000
|
||
db_list = pgsqlModel().get_list(args)['message']
|
||
for db in db_list["data"]:
|
||
if db["name"] == depDataBase:
|
||
args.id = db["id"]
|
||
args.name = db["name"]
|
||
pgsqlModel().DeleteDatabase(args)
|
||
break
|
||
|
||
# 2024/8/5 下午6:25 获取指定数据库的sid
|
||
def get_database_sid(self, get):
|
||
'''
|
||
@name 获取指定数据库的sid
|
||
'''
|
||
from database import database
|
||
db_list = database().GetCloudServer(get)
|
||
for db in db_list:
|
||
if get.db_host == db["ps"]:
|
||
return db["id"]
|
||
return False
|
||
|
||
# 2024/8/5 下午6:25 获取指定数据库的sid
|
||
def get_pgsql_database_sid(self, get):
|
||
'''
|
||
@name 获取指定pgsql数据库的sid
|
||
'''
|
||
from databaseModelV2.pgsqlModel import main as pgsqlModel
|
||
args = public.dict_obj()
|
||
args.search = get.db_host
|
||
args.table = "databases"
|
||
args.p = 1
|
||
args.limit = 20000
|
||
args.type = 'pgsql'
|
||
db_list = pgsqlModel().GetCloudServer(args)['message']
|
||
for db in db_list:
|
||
if get.db_host == db["ps"]:
|
||
return db["id"]
|
||
return False
|
||
|
||
# 2024/8/1 上午10:36 构造返回
|
||
def structure_installed_apps(self, app_type, sk_container_list, installed_json, query=None):
|
||
'''
|
||
@name 构造返回
|
||
'''
|
||
installed_apps = []
|
||
current_timestamp = int(time.time())
|
||
# from btdockerModelV2 import dk_public as dp
|
||
server_ip = public.GetLocalIp()
|
||
for i in installed_json[app_type]:
|
||
i["server_ip"] = server_ip
|
||
# if not "site_id" in i.keys():
|
||
# i["site_id"] = None
|
||
# i["site_name"] = None
|
||
# i["site_addtime"] = None
|
||
|
||
# if not i["domain"] is None and i["site_id"] is None:
|
||
# find_result = dp.sql("docker_sites").where("name=?", (i["domain"],)).find()
|
||
# if find_result:
|
||
# i["site_id"] = find_result["id"]
|
||
# i["site_name"] = i["domain"]
|
||
# i["site_addtime"] = find_result["addtime"]
|
||
# else:
|
||
# # 2024/11/21 15:18 如果网站没了则不显示域名
|
||
# i["domain"] = None
|
||
# # 2024/11/21 15:08 如果id查询异常则尝试重新添加一个网站;先不使用,用上面的逻辑
|
||
# # from mod.project.docker.sites.sitesManage import SitesManage
|
||
# # site_manage = SitesManage()
|
||
# #
|
||
# # args = public.to_dict_obj({
|
||
# # "name": i["service_name"],
|
||
# # "type": "app",
|
||
# # "domains": i["domain"],
|
||
# # "port": i["port"][0],
|
||
# # "remark": i["domain"],
|
||
# # })
|
||
# # create_result = site_manage.create_site(args)
|
||
# # # 2024/11/21 15:14 如果网站无法创建就不显示域名了
|
||
# # if not create_result['status']: i["domain"] = None
|
||
|
||
i["createTime"] = i["createat"]
|
||
time_diff = current_timestamp - i["createat"]
|
||
time_diff_delta = timedelta(seconds=time_diff)
|
||
days = time_diff_delta.days
|
||
hours = time_diff_delta.seconds // 3600
|
||
if days > 0:
|
||
i["createat"] = "{} days {} hours".format(days, hours)
|
||
else:
|
||
i["createat"] = "{} hours".format(hours)
|
||
|
||
if not query is None:
|
||
if (not query in i["appname"] and not query in i["apptitle"] and
|
||
not query in i["appdesc"] and not query in i["service_name"]):
|
||
continue
|
||
|
||
i["status"] = None
|
||
if not i["status"] is None and i["status"] != "running":
|
||
continue
|
||
|
||
if len(sk_container_list) == 0:
|
||
if os.path.exists("/tmp/{}.log".format(i["service_name"])):
|
||
i["status"] = "initializing"
|
||
else:
|
||
i["status"] = "exited"
|
||
if not i in installed_apps:
|
||
installed_apps.append(i)
|
||
continue
|
||
|
||
for j in sk_container_list:
|
||
i["container_id"] = j["Id"]
|
||
if not "createdBy" in j["Labels"].keys():
|
||
continue
|
||
if j["Labels"]["createdBy"] != "bt_apps":
|
||
continue
|
||
|
||
if "com.docker.compose.service" in j["Labels"].keys() and j["Labels"]["com.docker.compose.service"] == \
|
||
i["service_name"].lower():
|
||
i["status"] = j['State']
|
||
break
|
||
|
||
if "com.docker.compose.project" in j["Labels"].keys() and j["Labels"]["com.docker.compose.project"] == \
|
||
i["service_name"].lower():
|
||
i["status"] = j['State']
|
||
break
|
||
else:
|
||
if os.path.exists("/tmp/{}.log".format(i["service_name"])):
|
||
check_bt_successful = \
|
||
public.ExecShell("cat /tmp/{}.log | grep bt_successful".format(i["service_name"]))[0]
|
||
if check_bt_successful == "":
|
||
check_bt_failed = \
|
||
public.ExecShell("cat /tmp/{}.log | grep bt_failed".format(i["service_name"]))[0]
|
||
if check_bt_failed != "":
|
||
i["status"] = "exited"
|
||
else:
|
||
i["status"] = "initializing"
|
||
else:
|
||
if i["appname"] == "sftpgo":
|
||
check_started = \
|
||
public.ExecShell("cat /tmp/{}.log | grep Started".format(i["service_name"]))[0]
|
||
if check_started =="":
|
||
i["status"] = "initializing"
|
||
else:
|
||
i["status"] = "exited"
|
||
else:
|
||
i["status"] = "initializing"
|
||
|
||
i["canUpdate"] = 1 if self.check_canupdate(i) else 0
|
||
if i["appname"] == "jenkins":
|
||
jenkins_key_file = "{}/jenkins_key.pl".format(os.path.join(i["path"], i["service_name"]))
|
||
if not os.path.exists(jenkins_key_file):
|
||
cmd = "docker-compose -f {} exec -it {} cat /var/jenkins_home/secrets/initialAdminPassword".format(
|
||
os.path.join(i["path"], i["service_name"], "docker-compose.yml"), i["service_name"])
|
||
pass_key = public.ExecShell(cmd)[0]
|
||
if pass_key != "": public.writeFile(jenkins_key_file, pass_key)
|
||
else:
|
||
pass_key = public.readFile(jenkins_key_file)
|
||
|
||
if pass_key == "":
|
||
i["appinfo"].append({"fieldKey": "jenkins_pass_key", "fieldTitle": "jenkins key", "fieldValue": "Please wait for Jenkins to initialize and refresh the installed page to obtain the key!"})
|
||
else:
|
||
i["appinfo"].append({"fieldKey": "jenkins_pass_key", "fieldTitle": "jenkins key", "fieldValue": pass_key})
|
||
elif i["appname"] == "nginx_proxy_manager":
|
||
i["appinfo"].append({"fieldKey": "allow_access", "fieldTitle": "Default mailbox", "fieldValue": "admin@example.com"})
|
||
i["appinfo"].append({"fieldKey": "allow_access", "fieldTitle": "Default password", "fieldValue": "changeme"})
|
||
elif i["appname"] =="openlist" or i["appname"] == "openlist":
|
||
appname = i["appname"]
|
||
compose_file = "{}/{}/docker-compose.yml".format(i["path"], i["service_name"])
|
||
pass_file = "{}/{}/alist_pass.pl".format(i["path"], i["service_name"])
|
||
i["appinfo"].append({
|
||
"fieldKey": "{}_user".format(appname),
|
||
"fieldTitle": "{} account".format(appname),
|
||
"fieldValue": "admin",
|
||
})
|
||
if not os.path.exists(pass_file):
|
||
alist_password = public.GetRandomString(10)
|
||
i["appinfo"].append({
|
||
"fieldKey": "{}_password".format(appname),
|
||
"fieldTitle": "Set {} password (copy to terminal)".format(appname),
|
||
"fieldValue": "docker-compose -f {compose_file} exec -it {service_name} ./{bin} admin set {alist_password}".format(
|
||
bin=appname,
|
||
compose_file=compose_file,
|
||
service_name=i["service_name"],
|
||
alist_password=alist_password,
|
||
),
|
||
})
|
||
public.writeFile(pass_file, alist_password)
|
||
else:
|
||
alist_password = public.readFile(pass_file)
|
||
i["appinfo"].append({
|
||
"fieldKey": "{}_password".format(appname),
|
||
"fieldTitle": "{} password".format(appname),
|
||
"fieldValue": alist_password,
|
||
})
|
||
i["appinfo"].append({
|
||
"fieldKey": "{}_password".format(appname),
|
||
"fieldTitle": "Reset {} password (copy to terminal)".format(appname),
|
||
"fieldValue": "docker-compose -f {compose_file} exec -it {service_name} ./{bin} admin set {alist_password}".format(
|
||
bin=appname,
|
||
compose_file=compose_file,
|
||
service_name=i["service_name"],
|
||
alist_password=alist_password,
|
||
),
|
||
})
|
||
elif i["appname"] == "openvpn":
|
||
i["appinfo"].append({"fieldKey": "ovpnfile", "fieldTitle": "ovpn file (import client)", "fieldValue": "{}/{}/{}.ovpn".format(i["path"], i["service_name"], i["service_name"])})
|
||
elif i["appname"] == "rustdesk":
|
||
secret_key = public.readFile("{}/{}/data/id_ed25519.pub".format(i["path"], i["service_name"]))
|
||
i["appinfo"].append(
|
||
{"fieldKey": "secret_key", "fieldTitle": "密钥(key)", "fieldValue": "{}".format(secret_key)})
|
||
allow_access = "yes" if i["host_ip"] == "0.0.0.0" else "no" if i["domain"] is None else "yes"
|
||
i["appinfo"].append({"fieldKey": "allow_access", "fieldTitle": "Allow external access", "fieldValue": allow_access})
|
||
# if i["status"] == "created":
|
||
# i["status"] = "initializing"
|
||
if not i in installed_apps:
|
||
installed_apps.append(i)
|
||
|
||
return installed_apps
|
||
|
||
# 2024/8/1 下午4:05 根据apps_json最新版本与已装的版本对比,返回canupdate True/False
|
||
def check_canupdate(self, installed_app):
|
||
'''
|
||
@name 根据apps_json最新版本与已装的版本对比,返回canupdate True/False
|
||
'''
|
||
if installed_app["m_version"] in ("main", "latest"):
|
||
return False
|
||
if not self.apps_json or not isinstance(self.apps_json, (list, dict)):
|
||
return False
|
||
|
||
for app in self.apps_json:
|
||
if app["appname"] == installed_app["appname"]:
|
||
for version in app["appversion"]:
|
||
if version["m_version"] == installed_app["m_version"]:
|
||
for s_version in version["s_version"]:
|
||
if "." in s_version:
|
||
c_v = float(s_version)
|
||
else:
|
||
c_v = int(s_version)
|
||
|
||
if "." in installed_app["s_version"]:
|
||
i_v = float(installed_app["s_version"])
|
||
else:
|
||
i_v = int(installed_app["s_version"])
|
||
|
||
if c_v > i_v:
|
||
return True
|
||
return False
|
||
|
||
# 2024/8/1 下午9:59 停止指定app
|
||
def stop_app(self, get):
|
||
'''
|
||
@name 停止指定app
|
||
'''
|
||
get.service_name = get.get("service_name", None)
|
||
if get.service_name is None:
|
||
return public.return_message(-1, 0, public.lang("Please pass the service_name parameter!"))
|
||
get.app_name = get.get("app_name", None)
|
||
if get.app_name is None:
|
||
return public.return_message(-1, 0, public.lang("Please pass the app_name parameter!"))
|
||
|
||
self.set_service_name(get.service_name)
|
||
self.set_app_name(get.app_name)
|
||
self.set_app_path()
|
||
self.set_service_path()
|
||
self.set_compose_file()
|
||
command = self.set_type(0).set_path(self.compose_file).get_compose_stop()
|
||
stdout, stderr = public.ExecShell(command)
|
||
if stderr:
|
||
if not "Stopped" in stderr:
|
||
return public.return_message(-1, 0, public.lang("Stop failed: {}!".format(stderr)))
|
||
return public.return_message(0, 0, public.lang("Stop succeeding!"))
|
||
|
||
# 2024/8/1 下午10:02 启动指定app
|
||
def start_app(self, get):
|
||
'''
|
||
@name 启动指定app
|
||
'''
|
||
get.service_name = get.get("service_name", None)
|
||
if not self.service_name is None:
|
||
get.service_name = self.service_name
|
||
if get.service_name is None:
|
||
return public.return_message(-1, 0, public.lang("Please pass the service_name parameter!"))
|
||
get.app_name = get.get("app_name", None)
|
||
if not self.app_name is None:
|
||
get.app_name = self.app_name
|
||
if get.app_name is None:
|
||
return public.return_message(-1, 0, public.lang("Please pass the app_name parameter!"))
|
||
|
||
self.set_service_name(get.service_name)
|
||
self.set_app_name(get.app_name)
|
||
self.set_app_path()
|
||
self.set_cmd_log()
|
||
self.set_service_path()
|
||
self.set_compose_file()
|
||
compose_cmd = self.set_type(0).set_path(self.compose_file).get_compose_up_remove_orphans()
|
||
# command = ("nohup echo '正在启动,可能需要等待1-5分钟以上...' >> {app_cmd_log};"
|
||
# "{compose_cmd} >> {app_cmd_log} 2>&1 && "
|
||
# "echo 'bt_successful' >> {app_cmd_log} || echo 'bt_failed' >> {app_cmd_log} &"
|
||
# .format(
|
||
# compose_cmd=compose_cmd,
|
||
# app_cmd_log=self.app_cmd_log,
|
||
# compose_file=self.compose_file,
|
||
# ))
|
||
stdout, stderr = public.ExecShell(compose_cmd)
|
||
if stderr:
|
||
if "create failed" in stderr:
|
||
return public.return_message(-1, 0, public.lang("Startup failed: {}!",stderr))
|
||
if "Started" in stderr:
|
||
return public.return_message(0, 0, public.lang("The startup was successful!"))
|
||
if not "Running" in stderr:
|
||
return public.return_message(-1, 0, public.lang("Startup failed: {}!",stderr))
|
||
return public.return_message(0, 0, public.lang("The startup was successful!"))
|
||
|
||
# 2024/8/1 下午10:11 重启指定app
|
||
def restart_app(self, get):
|
||
'''
|
||
@name 重启指定app
|
||
'''
|
||
get.service_name = get.get("service_name", None)
|
||
if get.service_name is None:
|
||
return public.return_message(-1, 0, public.lang("Please pass the service_name parameter!"))
|
||
get.app_name = get.get("app_name", None)
|
||
if get.app_name is None:
|
||
return public.return_message(-1, 0, public.lang("Please pass the app_name parameter!"))
|
||
|
||
self.set_service_name(get.service_name)
|
||
self.set_app_name(get.app_name)
|
||
self.set_app_path()
|
||
self.set_service_path()
|
||
self.set_compose_file()
|
||
command = self.set_type(0).set_path(self.compose_file).get_compose_restart()
|
||
public.ExecShell(command)
|
||
return public.return_message(0, 0, public.lang("The reboot was successful!"))
|
||
|
||
# 2024/8/1 下午10:50 拉取指定app的镜像
|
||
def pull_app(self):
|
||
'''
|
||
@name 拉取指定app的镜像
|
||
'''
|
||
command = self.set_type(0).set_path(self.compose_file).get_compose_pull()
|
||
public.ExecShell(command)
|
||
|
||
# 2024/8/5 下午2:41 检查指定app模板是否存在
|
||
def check_app_template(self, get):
|
||
'''
|
||
@name 检查指定app模板是否存在
|
||
'''
|
||
get.force_update = get.get("force_update", False)
|
||
|
||
if get.force_update:
|
||
return self.download_app_template(get)
|
||
if not os.path.exists(self.app_template_path):
|
||
return self.download_app_template(get)
|
||
if not os.path.exists((os.path.join(self.app_template_path, "docker-compose.yml"))):
|
||
return self.download_app_template(get)
|
||
if not os.path.exists((os.path.join(self.app_template_path, ".env"))):
|
||
return self.download_app_template(get)
|
||
|
||
# 2024/8/5 下午2:42 下载并解压指定app的模版
|
||
def download_app_template(self, get):
|
||
'''
|
||
@name 下载并解压指定app的模版
|
||
'''
|
||
if os.path.exists(self.app_template_path):
|
||
public.ExecShell("rm -rf {}".format(self.app_template_path))
|
||
|
||
app_url = "{}/src/dk_app/yakpanel/apps/templates/{}.zip".format(public.get_url(), get.app_name)
|
||
# 检查GPU参数,重定向templates路径
|
||
if get.get('gpu', 'false') == 'true':
|
||
app_url = "{}/src/dk_app/yakpanel/apps/templates/{}_gpu.zip".format(public.get_url(), get.app_name)
|
||
to_file = '/tmp/{}.zip'.format(get.app_name)
|
||
if os.path.exists(to_file):
|
||
public.ExecShell("rm -f {}".format(to_file))
|
||
public.downloadFile(app_url, to_file)
|
||
if not os.path.exists(to_file) or os.path.getsize(to_file) < 10:
|
||
return public.return_message(-1, 0, public.lang("The download failed!"))
|
||
public.ExecShell("unzip -o -d {} {}".format(self.templates_path, to_file))
|
||
return public.return_message(0, 0, public.lang("The download was successful!"))
|
||
|
||
# 2024/8/5 下午6:19 创建指定app的数据库
|
||
def create_database(self, get):
|
||
'''
|
||
@name 创建指定app的数据库
|
||
'''
|
||
get.app_db = get.get("app_db", None)
|
||
if get.app_db is None:
|
||
return public.return_message(-1, 0, public.lang("Please pass the app db parameters!"))
|
||
get.db_username = get.get("db_username", None)
|
||
if get.db_username is None:
|
||
return public.return_message(-1, 0, public.lang("Please pass the username parameter!"))
|
||
get.db_password = get.get("db_password", None)
|
||
if get.db_password is None:
|
||
return public.return_message(-1, 0, public.lang("Please pass the password parameter!"))
|
||
|
||
db_sid = self.get_database_sid(get)
|
||
if not db_sid:
|
||
return public.return_message(-1, 0, public.lang("The specified database application was not found!"))
|
||
|
||
res = public.M("databases").where("name=? and sid=?", (get.app_db, db_sid)).find()
|
||
if res:
|
||
return public.return_message(0, 0, public.lang("The database already exists!"))
|
||
|
||
from database import database
|
||
args = public.dict_obj()
|
||
args.name = get.app_db
|
||
args.db_user = get.db_username
|
||
args.password = get.db_password
|
||
args.dataAccess = "%"
|
||
args.address = "%"
|
||
args.codeing = "utf8mb4"
|
||
args.dtype = "MySQL"
|
||
args.ps = get.app_db
|
||
args.sid = db_sid
|
||
args.listen_ip = "0.0.0.0/0"
|
||
create_res = database().AddDatabase(args)
|
||
if not create_res["status"]:
|
||
return public.return_message(-1, 0, create_res["msg"])
|
||
return public.return_message(0, 0, public.lang("The creation is successful!"))
|
||
|
||
# 2024/8/21 下午2:59 创建指定app的pgsql数据库
|
||
def create_pgsql_database(self, get):
|
||
'''
|
||
@name 创建指定app的pgsql数据库
|
||
'''
|
||
get.app_db = get.get("app_db", None)
|
||
if get.app_db is None:
|
||
return public.return_message(-1, 0, public.lang("Please pass the database parameter!"))
|
||
get.db_username = get.get("db_username", None)
|
||
if get.db_username is None:
|
||
return public.return_message(-1, 0, public.lang("Please pass the username parameter!"))
|
||
get.db_password = get.get("db_password", None)
|
||
if get.db_password is None:
|
||
return public.return_message(-1, 0, public.lang("Please pass the password parameter!"))
|
||
|
||
db_sid = self.get_pgsql_database_sid(get)
|
||
if not db_sid:
|
||
return public.return_message(-1, 0, public.lang("The specified database application was not found!"))
|
||
|
||
res = public.M("databases").where("name=? and sid=?", (get.app_db, db_sid)).find()
|
||
if res:
|
||
return public.return_message(0, 0, public.lang("The database already exists!"))
|
||
|
||
from databaseModelV2.pgsqlModel import main as pgsqlModel
|
||
args = public.dict_obj()
|
||
args.name = get.app_db
|
||
args.db_user = get.db_username
|
||
args.password = get.db_password
|
||
args.ps = get.app_db
|
||
args.sid = db_sid
|
||
args.listen_ip = "0.0.0.0/0"
|
||
create_res = pgsqlModel().AddDatabase(args)
|
||
if create_res["status"] == -1:
|
||
return public.return_message(-1, 0, create_res["message"])
|
||
return public.return_message(0, 0, public.lang("The creation is successful!"))
|
||
|
||
def find_field_value(self,data, target_key):
|
||
"""
|
||
用于从env中 找出某个env的值
|
||
eg:
|
||
[{host:0.0.0.0},{port:2222}] port -> 2222
|
||
|
||
参数:
|
||
- data: JSON 列表
|
||
- target_key: 要查找的 fieldKey
|
||
|
||
返回:
|
||
- 匹配的 fieldValue,如果未找到则返回 None
|
||
|
||
"""
|
||
for item in data:
|
||
if item.get("fieldKey") == target_key:
|
||
return item.get("fieldValue")
|
||
return None
|