| |
| |
| |
| |
| |
| |
| |
| |
| import json |
| import os |
| |
| |
| |
| import sys |
| import time |
|
|
| if "/www/server/panel/class" not in sys.path: |
| sys.path.insert(0, "/www/server/panel/class") |
|
|
| os.chdir("/www/server/panel") |
| import public |
| import panelMysql |
| import db_mysql |
|
|
| try: |
| from BTPanel import cache |
| except: |
| from cachelib import SimpleCache |
| cache = SimpleCache() |
|
|
|
|
| class main(): |
| def __init__(self): |
| |
| self._php_versions = ['52', '53', '54', '55', '56', '70', '71', '72', '73', '74', '80', '81', '82', '83'] |
| self._mysql_versions = ['5.1', '5.5', '5.6', '5.7', '8.0'] |
| |
| self._nginx_install = True |
| self._php_install = True |
| self._mysql_install = True |
| self._ftpd_install = True |
| self.APP_PACKAGE_DB_NAME = "BT_APP_PACKAGE_DB_NAME" |
| self.APP_PACKAGE_DB_USER = "BT_APP_PACKAGE_DB_USER" |
| self.APP_PACKAGE_DB_PASS = "BT_APP_PACKAGE_DB_PASS" |
| self._MYSQLDUMP_BIN = public.get_mysqldump_bin() |
| self._rewrite_file = "{panel_path}/vhost/rewrite/{site_name}.conf" |
| self._package_dir = "/www/backup/package" |
| self._upload_package_dir = "/www/backup/upload_package" |
| self._temp_backup_dir = "{}/temp".format(self._package_dir) |
| self._temp_upload_package_dir = "{}/temp".format(self._upload_package_dir) |
| self._upload_package_path = os.path.join(self._upload_package_dir, "{app_name}") |
| self._backup_dir = None |
| self.skey = "app_package_create" |
| self._package_conf = { |
| "app_name": "", |
| "app_version": "", |
| "exclude_dir": [], |
| "php_versions": [], |
| "php_libs": [], |
| "php_functions": "", |
| "mysql_versions": [], |
| "init_sql": 0, |
| "db_character": "", |
| "db_config_file": [], |
| "nginx_install": True, |
| "php_install": True, |
| "mysql_install": False, |
| "ftpd_install": True, |
| "run_path": "/", |
| "dir_permission": [], |
| "update_log": "", |
| "size": 0, |
| "success_url": "", |
| } |
|
|
| |
| def get_php_versions(self, get): |
| ''' |
| @name 返回支持选择的PHP列表 |
| @param "data":{"参数名":""} <数据类型> 参数描述 |
| @return dict{"status":True/False,"msg":"提示信息"} |
| ''' |
| return { |
| "used": public.get_site_php_version(get.site_name), |
| "versions": self._php_versions, |
| } |
|
|
| |
| def get_mysql_versions(self, get): |
| ''' |
| @name 返回支持的mysql列表 |
| @param "data":{"参数名":""} <数据类型> 参数描述 |
| @return dict{"status":True/False,"msg":"提示信息"} |
| ''' |
| used = "00" |
| if os.path.exists("{}/mysql/bin/mysqld".format(public.get_setup_path())): |
| version = public.ReadFile("{}/mysql/version.pl".format(public.get_setup_path())) |
| if version != "" and "." in version: |
| used = version.rsplit(".", 1)[0] |
|
|
| return { |
| "used": used if "." in used else "00", |
| "versions": self._mysql_versions, |
| } |
|
|
| |
| def get_php_config(self, get): |
| ''' |
| @name 获取指定版本PHP的当前配置情况 |
| @author wzz <2024/5/6 上午10:40> |
| @param "data":{"参数名":""} <数据类型> 参数描述 |
| @return dict{"status":True/False,"msg":"提示信息"} |
| ''' |
| get.version = get.get("version/s", "00") |
| if get.version == "00": |
| return public.returnResult(status=False, msg="php_version不能为空,请传入需要获取扩展的PHP版本") |
|
|
| import ajax |
| a = ajax.ajax() |
| res = a.GetPHPConfig(get) |
|
|
| is_install = [] |
| for r in res["libs"]: |
| if r["status"]: |
| is_install.append(r) |
|
|
| res["libs"] = is_install |
|
|
| return public.returnResult(status=True, data=res) |
|
|
| |
| def get_env_info(self, get): |
| ''' |
| @name 获取环境信息 |
| @author wzz <2024/5/8 下午4:31> |
| @param "data":{"参数名":""} <数据类型> 参数描述 |
| @return dict{"status":True/False,"msg":"提示信息"} |
| ''' |
| get.site_name = get.get("site_name/s", "") |
| if get.site_name == "": |
| return public.returnResult(status=False, msg="site_name不能为空") |
|
|
| result = cache.get(self.skey) |
| last_php_functions = "" |
| last_php_versions = "" |
| last_mysql_versions = "" |
| last_init_sql = 0 |
| last_db_name = "" |
| last_db_id = "" |
| last_db_config_files_l = [] |
| if isinstance(result, dict): |
| last_php_functions = result["php_functions"] if "php_functions" in result else "" |
| last_php_versions = result["php_versions"].split(",") if "php_versions" in result else "" |
| last_mysql_versions = result["mysql_versions"].split(",") if "mysql_versions" in result else "" |
| last_init_sql = result["init_sql"] if "init_sql" in result else 0 |
| last_db_config_files = result["db_config_files"] if "db_config_files" in result else [] |
| for db_c in last_db_config_files: |
| last_db_config_files_l.append({"file": db_c, "body": ""}) |
| last_db_name = result["db_name"] if "db_name" in result else "" |
| last_db_id = result["db_id"] if "db_id" in result else None |
|
|
| php_version = self.get_php_versions(get) |
| php_version["last_php_versions"] = last_php_versions |
| mysql_version = self.get_mysql_versions(get) |
| mysql_version["last_mysql_versions"] = last_mysql_versions |
| mysql_version["last_init_sql"] = last_init_sql |
| mysql_version["last_db_config_files"] = last_db_config_files_l |
| mysql_version["last_db_name"] = last_db_name |
| mysql_version["last_db_id"] = last_db_id |
|
|
| data = { |
| "php": php_version, |
| "mysql": mysql_version, |
| "db": { |
| "used": {}, |
| "all": [], |
| }, |
| "db_config_file": [], |
| "last_php_functions": last_php_functions, |
| } |
|
|
| get.site_info = public.M('sites').where('name=?', (get.site_name,)).find() |
| if not get.site_info: |
| return public.returnResult(status=False, msg="获取网站信息失败") |
|
|
| get.db_info = public.M('databases').where('pid=?', (get.site_info['id'],)).find() |
| get.db_all = public.M('databases').select() |
| data["db"]["all"] = get.db_all |
| get.config_list = [] |
| if get.db_info: |
| data["db"]["used"] = get.db_info |
|
|
| stdout, stderr = public.ExecShell("find {site_path}/* -name *.php|xargs grep \"{db_name}\"".format( |
| site_path=get.site_info["path"], |
| db_name=get.db_info["name"], |
| )) |
| find_result = stdout.split("\n") |
| for fr in find_result: |
| if not fr: |
| continue |
|
|
| find_file = fr.split(":")[0] |
| if not os.path.exists(find_file): |
| continue |
| if not find_file.endswith(".php"): |
| continue |
| find_body = fr.split(":")[1] |
| if not find_body: |
| continue |
|
|
| if len(get.config_list) > 0: |
| for conf in get.config_list: |
| if find_file in conf["file"]: |
| break |
| else: |
| get.config_list.append({"file": find_file, "body": find_body}) |
| else: |
| get.config_list.append({"file": find_file, "body": find_body}) |
|
|
| data["db_config_file"] = get.config_list |
| self._package_conf["db_config_file"] = get.config_list |
|
|
| return public.returnResult(status=True, data=data) |
|
|
| |
| def get_path_permission(self, get): |
| ''' |
| @name 获取指定目录的权限信息 |
| @author wzz <2024/5/6 下午3:51> |
| @param "data":{"参数名":""} <数据类型> 参数描述 |
| @return dict{"status":True/False,"msg":"提示信息"} |
| ''' |
| try: |
| import pwd |
| site_path_stat = os.stat(get.check_path) |
| info = pwd.getpwuid(site_path_stat.st_uid) |
|
|
| return { |
| "path": get.check_path, |
| "pw_name": info.pw_name, |
| "st_mode": site_path_stat.st_mode, |
| } |
| except Exception as e: |
| return {} |
|
|
| |
| def scan_directory(self, directory): |
| for root, dirs, files in os.walk(directory): |
| yield root, dirs, files |
| |
| if root.count(os.sep) >= directory.count(os.sep) + 2: |
| del dirs[:] |
|
|
| |
| def get_dir_list(self, get): |
| ''' |
| @name 根据目录获取最多两层目录 |
| @param "data":{"参数名":""} <数据类型> 参数描述 |
| @return dict{"status":True/False,"msg":"提示信息"} |
| ''' |
| get.path = get.site_info["path"] |
| get.dir_permission_list = [] |
| has_root = False |
| root_path = "" |
| for root, dirs, files in self.scan_directory(get.path): |
| if not has_root: |
| get.check_path = root |
| path_perm = self.get_path_permission(get) |
| path_perm["path"] = "/" |
| if path_perm: |
| get.dir_permission_list.append(path_perm) |
| has_root = True |
| root_path = root |
|
|
| if len(dirs) > 0: |
| for d in dirs: |
| get.check_path = os.path.join(root, d) |
| path_perm = self.get_path_permission(get) |
| path_perm["path"] = get.check_path.replace(root_path, "") |
| if path_perm: |
| get.dir_permission_list.append(path_perm) |
|
|
| if len(files) > 0: |
| for f in files: |
| get.check_path = os.path.join(root, f) |
| path_perm = self.get_path_permission(get) |
| path_perm["path"] = get.check_path.replace(root_path, "") |
| if path_perm: |
| get.dir_permission_list.append(path_perm) |
|
|
| |
| def set_path_permission(self, get): |
| ''' |
| @name 为指定目录设置权限 |
| @author wzz <2024/5/6 下午3:52> |
| @param get.path/s: 指定目录 |
| get.permission/dict = { |
| "pw_name": "root", |
| "st_mode": 16877 |
| } |
| @return dict{"status":True/False,"msg":"提示信息"} |
| ''' |
| try: |
| import pwd |
| import stat |
| pw_info = pwd.getpwnam(get.permission["pw_name"]) |
| public.ExecShell("chown -R {}:{} {}".format(pw_info.pw_uid, pw_info.pw_gid, get.path)) |
| public.ExecShell("chmod -R {} {}".format(stat.S_IMODE(get.permission["st_mode"]), get.path)) |
|
|
| |
| site_path_stat = os.stat(get.path) |
| info = pwd.getpwuid(site_path_stat.st_uid) |
| if info.pw_name == get.permission["pw_name"] and site_path_stat.st_mode == get.permission["st_mode"]: |
| return public.returnResult(status=True, msg="设置成功") |
| else: |
| return public.returnResult(status=False, msg="设置失败") |
| except Exception as e: |
| return public.returnResult(status=False, msg="设置失败: {}".format(str(e))) |
|
|
| |
| def get_site_permission(self, get): |
| ''' |
| @name 获取指定网站的根目录权限和运行目录权限 |
| @param "data":{"参数名":""} <数据类型> 参数描述 |
| @return dict{"status":True/False,"msg":"提示信息"} |
| ''' |
| try: |
| get.check_path = get.site_info["path"] |
| get.root_path_permission = self.get_path_permission(get) |
| get.root_path_permission.pop("path") |
| from panelSite import panelSite |
| site_obj = panelSite() |
| get.id = get.site_info["id"] |
| runPath = site_obj.GetSiteRunPath(get) |
| get.check_path = get.site_info["path"] + runPath["runPath"] |
| get.run_path = runPath["runPath"] |
| get.run_path_permission = self.get_path_permission(get) |
| get.run_path_permission.pop("path") |
|
|
| |
| get.dir_permission = { |
| "root_permission": get.root_path_permission, |
| "run_permission": get.run_path_permission, |
| } |
| except Exception as e: |
| get.dir_permission = {} |
|
|
| |
| def get_os_type(self): |
| ''' |
| @name 获取系统类型 |
| @author wzz <2024/5/6 下午5:02> |
| @param "data":{"参数名":""} <数据类型> 参数描述 |
| @return dict{"status":True/False,"msg":"提示信息"} |
| ''' |
| if os.path.exists('/usr/bin/yum'): |
| return "1" |
| elif os.path.exists('/usr/bin/apt-get'): |
| return "3" |
| else: |
| return "0" |
|
|
| |
| def install_env_soft(self, get): |
| ''' |
| @name 安装指定运行环境 |
| @author wzz <2024/5/6 下午4:55> |
| @param "data":{"参数名":""} <数据类型> 参数描述 |
| @return dict{"status":True/False,"msg":"提示信息"} |
| ''' |
| get.lib_name = get.get("name/s", "") |
| get.version = get.get("version/s", "") |
| if get.lib_name == "" or get.version == "": |
| return public.returnResult(status=False, msg="name或version不能为空") |
|
|
| |
| mmsg = "安装[{}]".format(get.lib_name + "-" + get.version) |
| if public.M('tasks').where('name=? and status=?', (mmsg, "-1")).count(): |
| return public.returnMsg(False, "已存在安装任务,请勿重复添加!") |
|
|
| public.ExecShell("rm -rf {}/install/{}.sh".format(public.get_panel_path(), get.lib_name)) |
| execstr = ("wget -O /tmp/{name}.sh {url}/install/{os_type}/{name}.sh && " |
| "bash /tmp/{name}.sh install {version}").format( |
| name=get.lib_name, |
| url=public.get_url(), |
| os_type=self.get_os_type(), |
| version=get.version, |
| ) |
| public.M('tasks').add('id,name,type,status,addtime,execstr', |
| (None, mmsg, 'execshell', '0', time.strftime('%Y-%m-%d %H:%M:%S'), execstr)) |
|
|
| return public.returnResult(status=True, msg="安装任务添加成功") |
|
|
| |
| def tar_path(self, get): |
| ''' |
| @name 将指定目录压缩成tar.gz包 |
| @param "data":{"参数名":""} <数据类型> 参数描述 |
| @return dict{"status":True/False,"msg":"提示信息"} |
| ''' |
| get.path = get.get("path/s", "") |
| if get.path == "": |
| return public.returnResult(status=False, msg="path不能为空") |
|
|
| get.target_path = get.get("target_path/s", "") |
| if get.target_path == "": |
| return public.returnResult(status=False, msg="target_path不能为空") |
|
|
| if not os.path.exists(get.target_path): |
| public.ExecShell("mkdir -p {}".format(get.target_path)) |
| if not os.path.isdir(get.target_path): |
| return public.returnResult(status=False, msg="保存位置必须是一个目录") |
|
|
| get.package_name = get.get("package_name/s", "") |
| if get.package_name == "": |
| return public.returnResult(status=False, msg="package_name不能为空") |
| get.package_name = get.package_name.replace(".tar.gz", "") |
|
|
| |
| exclude = [ |
| get.path + "/.git", |
| get.path + "/.svn", |
| get.path + "/.idea", |
| get.path + "/.vscode", |
| get.path + "/.vs", |
| get.path + "/.github", |
| get.path + "/.gitignore", |
| get.path + "/.gitattributes", |
| get.path + "/.gitmodules", |
| get.path + "/.gitkeep", |
| get.path + "/.gitlab-ci.yml", |
| get.path + "/.gitlab", |
| get.path + "/.gitlab-ci", |
| get.path + "/.user.ini", |
| ] |
| try: |
| exclude.extend(get.exclude_dir) |
| except: |
| pass |
|
|
| exclude_str = "" |
| for e in exclude: |
| if not os.path.exists(e): |
| continue |
|
|
| exclude_str += " --exclude='{}'".format(e) |
|
|
| temp_sites_path = os.path.join(self._temp_backup_dir, "temp_sites") |
| if not os.path.exists(temp_sites_path): |
| public.ExecShell("mkdir -p {}".format(temp_sites_path)) |
| if not os.path.exists(os.path.join(temp_sites_path, get.app_name)): |
| public.ExecShell("mkdir -p {}".format(os.path.join(temp_sites_path, get.app_name))) |
| public.ExecShell("\cp -r {path}/* {temp_sites_path}/{app_name}/".format( |
| path=get.path, |
| temp_sites_path=temp_sites_path, |
| app_name=get.app_name, |
| )) |
|
|
| public.ExecShell( |
| "cd {temp_sites_path} && tar -zcvf {target_path}/{package_name}.tar.gz {exclude_str} {target_dir} ".format( |
| temp_sites_path=temp_sites_path, |
| target_path=get.target_path, |
| package_name=get.package_name, |
| exclude_str=exclude_str, |
| target_dir=get.app_name, |
| )) |
|
|
| if not os.path.exists("{}/{}.tar.gz".format(get.target_path, get.package_name)): |
| return public.returnResult(status=False, msg="打包失败") |
|
|
| return public.returnResult(status=True, msg="打包成功") |
|
|
| def __get_db_name_config(self, db_name: str): |
| from database import database |
| database = database() |
| db_find = public.M("databases").where("name=? AND LOWER(type)=LOWER('mysql')", (db_name,)).find() |
|
|
| if db_find["db_type"] == 0: |
| result = panelMysql.panelMysql().execute("show databases") |
| isError = database.IsSqlError(result) |
| if isError: |
| return public.returnResult(status=False, msg=isError) |
| db_password = public.M("config").where("id=?", (1,)).getField("mysql_root") |
| if not db_password: |
| return public.returnResult(status=False, msg="数据库密码为空!请先设置数据库密码!") |
| try: |
| db_port = int(panelMysql.panelMysql().query("show global variables like 'port'")[0][1]) |
| except: |
| db_port = 3306 |
| if not db_password: |
| return public.returnResult(status=False, msg="{} 数据库密码不能为空".format(db_find["name"])) |
| conn_config = { |
| "db_host": "localhost", |
| "db_port": db_port, |
| "db_user": db_find["username"], |
| "db_password": db_find["password"], |
| } |
| elif db_find["db_type"] == 1: |
| |
| conn_config = json.loads(db_find["conn_config"]) |
| res = database.CheckCloudDatabase(conn_config) |
| if isinstance(res, dict): return public.returnResult(status=False, msg=res) |
| conn_config["db_port"] = int(conn_config["db_port"]) |
| elif db_find["db_type"] == 2: |
| conn_config = public.M("database_servers").where("id=? AND LOWER(db_type)=LOWER('mysql')", |
| db_find["sid"]).find() |
| res = database.CheckCloudDatabase(conn_config) |
| if isinstance(res, dict): return public.returnResult(status=False, msg=res) |
| conn_config["db_name"] = None |
| conn_config["db_port"] = int(conn_config["db_port"]) |
| else: |
| return public.returnResult(status=False, msg="{} 未知的数据库类型".format(db_find["name"])) |
| return public.returnResult(status=True, data=conn_config) |
|
|
| |
| def backup_database(self, get): |
| ''' |
| @name 备份指定数据库为sql文件 |
| @author wzz <2024/5/7 上午10:28> |
| @param "data":{"参数名":""} <数据类型> 参数描述 |
| @return dict{"status":True/False,"msg":"提示信息"} |
| ''' |
| get.db_name = get.get("db_name/s", "") |
| if get.db_name == "": |
| return public.returnResult(status=False, msg="db_name不能为空") |
| get.db_id = get.get("db_id/s", "") |
| if get.db_id == "": |
| return public.returnResult(status=False, msg="db_id不能为空") |
|
|
| if not os.path.exists(self._MYSQLDUMP_BIN): |
| return public.returnResult(status=False, msg="缺少备份工具,请先通过软件管理安装MySQL!") |
|
|
| db_find = public.M("databases").where("id=? AND name=? AND LOWER(type)=LOWER('mysql')", |
| (get.db_id, get.db_name)).find() |
| if not db_find: |
| return public.returnResult(status=False, msg="数据库[{}]不存在".format(get.db_name)) |
|
|
| from database import database |
| database = database() |
|
|
| db_name = db_find["name"] |
|
|
| conn_config = self.__get_db_name_config(db_name) |
| if not conn_config["status"]: |
| return conn_config |
|
|
| conn_config = conn_config["data"] |
|
|
| mysql_obj = db_mysql.panelMysql() |
| flag = mysql_obj.set_host( |
| conn_config["db_host"], |
| conn_config["db_port"], |
| None, |
| conn_config["db_user"], |
| conn_config["db_password"] |
| ) |
|
|
| if flag is False: |
| return public.returnMsg(False, database.GetMySQLError(mysql_obj._ex)) |
|
|
| |
| self._MYSQL_BACKUP_DIR = "/www/backup/database" |
| db_backup_dir = os.path.join(self._MYSQL_BACKUP_DIR, db_name) |
| if not os.path.exists(db_backup_dir): |
| os.makedirs(db_backup_dir) |
|
|
| file_name = "{db_name}_{backup_time}_mysql_data_{number}".format( |
| db_name=db_name, |
| backup_time=time.strftime("%Y-%m-%d_%H-%M-%S", time.localtime()), |
| number=public.GetRandomString(5), |
| ) |
|
|
| get.db_charset = public.get_database_character(db_name) |
| self._package_conf["db_character"] = get.db_charset |
|
|
| set_gtid_purged = "" |
| resp = public.ExecShell("{} --help | grep set-gtid-purged >> /tmp/backup_sql.log".format( |
| self._MYSQLDUMP_BIN))[0] |
| if resp.find("--set-gtid-purged") != -1: |
| set_gtid_purged = "--set-gtid-purged=OFF" |
|
|
| if db_find["db_type"] == 2: |
| db_user = conn_config["db_user"] |
| db_password = conn_config["db_password"] |
| db_port = int(conn_config["db_port"]) |
| else: |
| db_user = "root" |
| db_password = public.M("config").where("id=?", (1,)).getField("mysql_root") |
| db_port = conn_config["db_port"] |
|
|
| shell = "'{mysqldump_bin}' {set_gtid_purged} --opt --skip-lock-tables --single-transaction --routines --events --skip-triggers --default-character-set='{db_charset}' --force " \ |
| "--host='{db_host}' --port={db_port} --user='{db_user}' --password='{db_password}' '{db_name}'".format( |
| mysqldump_bin=self._MYSQLDUMP_BIN, |
| set_gtid_purged=set_gtid_purged, |
| db_charset=get.db_charset, |
| db_host=conn_config["db_host"], |
| db_port=db_port, |
| db_user=db_user, |
| db_password=db_password, |
| db_name=db_name, |
| ) |
|
|
| get.export_file = os.path.join(db_backup_dir, file_name + ".sql") |
| shell += "| tee /tmp/backup_sql.log > '{backup_path}' ".format(backup_path=get.export_file) |
| public.ExecShell(shell, env={"MYSQL_PWD": conn_config["db_password"]}) |
|
|
| if not os.path.exists(get.export_file): |
| return public.returnResult(status=False, msg="备份失败") |
|
|
| return public.returnResult(status=True, msg="备份成功", data={"file": get.export_file}) |
|
|
| |
| def backup_rewrite(self, get): |
| ''' |
| @name 备份指定网站的伪静态 |
| @author wzz <2024/5/7 下午5:41> |
| @param "data":{"参数名":""} <数据类型> 参数描述 |
| @return dict{"status":True/False,"msg":"提示信息"} |
| ''' |
| get.site_name = get.get("site_name/s", "") |
| if get.site_name == "": |
| return public.returnResult(status=False, msg="site_name不能为空") |
|
|
| self._rewrite_file = self._rewrite_file.format(panel_path=public.get_panel_path(), site_name=get.site_name) |
| if not os.path.exists(self._rewrite_file): |
| return public.returnResult(status=True, msg="伪静态文件不存在,不需要备份") |
|
|
| public.ExecShell("\cp -r {rewrite_file} {backup_dir}/rewrite.conf".format( |
| rewrite_file=self._rewrite_file, |
| backup_dir=self._backup_dir) |
| ) |
| if not os.path.exists("{}/rewrite.conf".format(self._backup_dir)): |
| return public.returnResult(status=False, msg="备份失败") |
|
|
| return public.returnResult(status=True, msg="备份成功") |
|
|
| |
| def restore_rewrite(self, get): |
| ''' |
| @name 还原指定包的伪静态到指定网站中 |
| @author wzz <2024/5/9 下午2:20> |
| @param "data":{"参数名":""} <数据类型> 参数描述 |
| @return dict{"status":True/False,"msg":"提示信息"} |
| ''' |
| self._rewrite_file = self._rewrite_file.format(panel_path=public.get_panel_path(), site_name=get.site_name) |
|
|
| public.ExecShell("\cp -r {_temp_import_dir}/{app_name}/rewrite.conf {_rewrite_file}".format( |
| _temp_import_dir=self._temp_import_dir, |
| app_name=get.app_name, |
| _rewrite_file=self._rewrite_file, |
| )) |
|
|
| |
| def restore_upload_rewrite(self, get): |
| ''' |
| @name 还原指定上传包的伪静态到指定网站中 |
| @author wzz <2024/5/9 下午6:05> |
| @param "data":{"参数名":""} <数据类型> 参数描述 |
| @return dict{"status":True/False,"msg":"提示信息"} |
| ''' |
| self._rewrite_file = self._rewrite_file.format(panel_path=public.get_panel_path(), site_name=get.site_name) |
|
|
| public.ExecShell("\cp -r {_upload_package_path}/{app_name}/rewrite.conf {_rewrite_file}".format( |
| _upload_package_path=self._upload_package_path, |
| app_name=get.app_name, |
| _rewrite_file=self._rewrite_file, |
| )) |
|
|
| |
| def get_db_config_file(self, get): |
| ''' |
| @name 获取指定数据库连接配置文件的相对路径,并将匹配到的数据库账号密码和数据库名 |
| @author wzz <2024/5/8 上午9:45> |
| @param "data":{"参数名":""} <数据类型> 参数描述 |
| @return dict{"status":True/False,"msg":"提示信息"} |
| ''' |
| if len(get.db_config_files) == 0: |
| return public.returnResult(status=False, msg="数据库配置文件不能为空,请选择.php文件") |
|
|
| get.config_list = [] |
| for db_conf in get.db_config_files: |
| if not db_conf: |
| continue |
| if not os.path.exists(db_conf): |
| return public.returnResult(status=False, msg="{}不存在".format(db_conf)) |
| if not db_conf.endswith(".php"): |
| return public.returnResult(status=False, msg="{}不是PHP文件".format(db_conf)) |
|
|
| |
| conf_body = public.readFile(db_conf) |
| if not conf_body: |
| return public.returnResult(status=False, msg="{}内容为空".format(db_conf)) |
|
|
| db_find = public.M("databases").where("id=? AND name=? AND LOWER(type)=LOWER('mysql')", |
| (get.db_id, get.db_name)).find() |
| if db_find: |
| conf_body = conf_body.replace(db_find["username"], self.APP_PACKAGE_DB_USER) |
| conf_body = conf_body.replace(db_find["name"], self.APP_PACKAGE_DB_NAME) |
| conf_body = conf_body.replace(db_find["password"], self.APP_PACKAGE_DB_PASS) |
| public.writeFile(db_conf, conf_body) |
|
|
| get.config_list.append(db_conf.replace(get.path + "/", "")) |
| self._package_conf["db_config_file"] = get.config_list |
|
|
| return public.returnResult(status=True, msg="据库连接配置文件处理成功") |
|
|
| |
| def update_package_conf(self, get): |
| ''' |
| @name 更新json配置文件 |
| @author wzz <2024/5/7 下午6:32> |
| @param "data":{"参数名":""} <数据类型> 参数描述 |
| @return dict{"status":True/False,"msg":"提示信息"} |
| ''' |
| self._package_conf["app_name"] = get.app_name |
| self._package_conf["app_version"] = get.app_version |
| self._package_conf["exclude_dir"] = get.exclude_dir |
| self._package_conf["php_versions"] = get.php_versions |
| self._package_conf["php_functions"] = get.php_functions |
| self._package_conf["mysql_versions"] = get.mysql_versions |
| self._package_conf["init_sql"] = get.init_sql |
| self._package_conf["run_path"] = get.run_path |
| self._package_conf["dir_permission"] = get.dir_permission |
| self._package_conf["update_log"] = get.update_log |
|
|
| public.writeFile("{}/dir_permission.json".format(self._backup_dir), json.dumps(get.dir_permission_list)) |
| public.writeFile("{}/package.json".format(self._backup_dir), json.dumps(self._package_conf)) |
|
|
| |
| def tar_package(self, get): |
| ''' |
| @name 将所有数据打包成一个压缩包 |
| @author wzz <2024/5/8 上午10:06> |
| @param "data":{"参数名":""} <数据类型> 参数描述 |
| @return dict{"status":True/False,"msg":"提示信息"} |
| ''' |
| get.package_name = get.app_name + "_v" + get.app_version |
| get.app_package_dir = os.path.join(self._package_dir, get.app_name) |
| if not os.path.exists(get.app_package_dir): |
| public.ExecShell("mkdir -p {}".format(get.app_package_dir)) |
|
|
| if get.export_file != "": |
| public.ExecShell("\cp -r {export_file} {temp_backup_dir}/packages/{app_name}/init.sql".format( |
| export_file=get.export_file, |
| temp_backup_dir=self._temp_backup_dir, |
| app_name=get.app_name, |
| )) |
|
|
| public.ExecShell( |
| "cd {temp_backup_dir}/packages/ && tar -zcvf {app_package_dir}/{package_name}.tar.gz {app_name}".format( |
| temp_backup_dir=self._temp_backup_dir, |
| app_package_dir=get.app_package_dir, |
| package_name=get.package_name, |
| app_name=get.app_name, |
| )) |
|
|
| public.ExecShell("rm -rf {}/*".format(self._temp_backup_dir)) |
|
|
| if not os.path.exists("{}/{}.tar.gz".format(get.app_package_dir, get.package_name)): |
| return public.returnResult(status=False, msg="打包失败") |
|
|
| get.size = os.path.getsize("{}/{}.tar.gz".format(get.app_package_dir, get.package_name)) |
|
|
| return public.returnResult(status=True, msg="打包成功", |
| data={"file": "{}/{}.tar.gz".format(get.app_package_dir, get.package_name)}) |
|
|
| |
| def update_database(self, get): |
| ''' |
| @name 更新数据库 |
| @author wzz <2024/5/8 下午3:34> |
| @param "data":{"参数名":""} <数据类型> 参数描述 |
| @return dict{"status":True/False,"msg":"提示信息"} |
| ''' |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| find_version = public.M('app_package').where('site_name=? AND app_name=? AND app_version=?', |
| (get.site_name, get.app_name, get.app_version)).find() |
|
|
| try: |
| php_libs = json.dumps(self._package_conf["php_libs"]) |
| except: |
| php_libs = "[]" |
|
|
| if find_version and "site_name" in find_version: |
| public.M('app_package').where('id=?', (find_version["id"],)).save( |
| 'package_name,package_path,size,update_log,addtime,php_versions,php_libs,php_functions,mysql_versions,db_character,init_sql,db_config_file', |
| (get.package_name, "{}/{}.tar.gz".format(get.app_package_dir, get.package_name), get.size, |
| get.update_log, time.strftime('%Y-%m-%d %H:%M:%S'), get.php_versions, php_libs, get.php_functions, |
| get.mysql_versions, get.db_charset, get.init_sql, json.dumps(get.config_list)) |
| ) |
| else: |
| public.M('app_package').add( |
| 'pid,site_name,app_name,app_version,package_name,package_path,size,addtime,update_log,php_libs,php_versions,php_functions,mysql_versions,db_character,init_sql,db_config_file', |
| (get.site_info["id"], get.site_name, get.app_name, get.app_version, get.package_name, |
| "{}/{}.tar.gz".format(get.app_package_dir, get.package_name), get.size, |
| time.strftime('%Y-%m-%d %H:%M:%S'), get.update_log, php_libs, get.php_versions, get.php_functions, |
| get.mysql_versions, get.db_charset, get.init_sql, json.dumps(get.config_list)) |
| ) |
|
|
| |
| def update_upload_database(self, get): |
| ''' |
| @name 更新上传应用包的数据库 |
| @author wzz <2024/5/9 下午4:43> |
| @param "data":{"参数名":""} <数据类型> 参数描述 |
| @return dict{"status":True/False,"msg":"提示信息"} |
| ''' |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| find_version = public.M('app_package_upload').where('app_name=? AND app_version=?', |
| (get.app_name, get.package_info["app_version"])).find() |
|
|
| try: |
| php_libs = json.dumps(get.package_info["php_libs"]) |
| except: |
| php_libs = "[]" |
|
|
| self._upload_package_path = self._upload_package_path.format(app_name=get.app_name) |
|
|
| if find_version and "app_name" in find_version: |
| public.M('app_package_upload').where('id=?', (find_version["id"],)).save( |
| 'package_path,size,update_log,addtime,php_versions,php_libs,php_functions,mysql_versions,db_character,init_sql,db_config_file', |
| (self._upload_package_path, get.size, get.package_info["update_log"], |
| time.strftime('%Y-%m-%d %H:%M:%S'), get.package_info["php_versions"], php_libs, get.package_info["php_functions"], |
| get.package_info["mysql_versions"], get.package_info["db_character"], get.package_info["init_sql"], |
| json.dumps(get.package_info["db_config_file"])) |
| ) |
| else: |
| public.M('app_package_upload').add( |
| 'app_name,app_version,package_path,size,addtime,update_log,php_libs,php_versions,php_functions,mysql_versions,db_character,init_sql,db_config_file', |
| (get.app_name, get.package_info["app_version"], |
| self._upload_package_path, get.size, |
| time.strftime('%Y-%m-%d %H:%M:%S'), get.package_info["update_log"], php_libs, get.package_info["php_versions"], |
| get.package_info["php_functions"], get.package_info["mysql_versions"], get.package_info["db_character"], |
| get.package_info["init_sql"], json.dumps(get.package_info["db_config_file"])) |
| ) |
|
|
| |
| def create(self, get): |
| ''' |
| @name 创建一件应用环境包 |
| @author wzz <2024/5/6 上午10:50> |
| @param "data":{"参数名":""} <数据类型> 参数描述 |
| @return dict{"status":True/False,"msg":"提示信息"} |
| ''' |
| get.site_name = get.get("site_name/s", "") |
| if get.site_name == "": |
| return public.returnResult(status=False, msg="site_name不能为空") |
|
|
| get.app_name = get.get("app_name/s", "") |
| if get.app_name == "": |
| return public.returnResult(status=False, msg="app_name不能为空") |
| get.app_version = get.get("app_version/s", "") |
| if get.app_version == "": |
| return public.returnResult(status=False, msg="app_version不能为空") |
|
|
| get.php_versions = get.get("php_versions/s", "00") |
| |
| get.php_functions = get.get("php_functions/s", "") |
| get.mysql_versions = get.get("mysql_versions/s", "00") |
| get.init_sql = int(get.get("init_sql/d", 0)) |
| get.db_name = get.get("db_name/s", "") |
| if get.db_name == "" and get.init_sql == 1: |
| return public.returnResult(status=False, msg="db_name不能为空") |
| get.db_id = get.get("db_id/s", "") |
| if get.db_id == "" and get.init_sql == 1: |
| return public.returnResult(status=False, msg="db_id不能为空") |
|
|
| get.exclude_dir = get.get("exclude_dir", "[]") |
| if type(get.exclude_dir) == str: |
| try: |
| get.exclude_dir = json.loads(get.exclude_dir) |
| except: |
| get.exclude_dir = [] |
| else: |
| get.exclude_dir = [] |
|
|
| get.db_config_files = get.get("db_config_files", "[]") |
| if type(get.db_config_files) == str: |
| get.db_config_files = json.loads(get.db_config_files) |
|
|
| get.success_url = get.get("success_url/s", "") |
| if not get.success_url.startswith("/"): |
| get.success_url = get.success_url + "/" |
| self._package_conf["success_url"] = get.success_url |
|
|
| get.update_log = get.get("update_log/s", "") |
| get.update_log = public.xssencode2(get.update_log) |
|
|
| |
| get.version = public.get_site_php_version(get.site_name) |
| if get.version != "00": |
| php_config = self.get_php_config(get) |
| self._package_conf["php_libs"] = php_config["data"]["libs"] |
| self._package_conf["php_functions"] = get.php_functions |
|
|
| |
| self._backup_dir = os.path.join(self._temp_backup_dir, "packages", get.app_name) |
| if os.path.exists(self._backup_dir): |
| public.ExecShell("rm -rf {}".format(self._backup_dir)) |
| public.ExecShell("mkdir -p {}".format(self._backup_dir)) |
|
|
| get.site_info = public.M('sites').where('name=?', (get.site_name,)).find() |
| if not get.site_info: |
| return public.returnResult(status=False, msg="获取网站信息失败") |
|
|
| get.path = get.site_info["path"] |
| get.target_path = self._backup_dir |
| get.package_name = get.app_name |
|
|
| |
| get.export_file = "" |
| get.db_charset = "" |
| get.config_list = [] |
| if get.init_sql == 1: |
| bk_result = self.backup_database(get) |
| if not bk_result["status"]: |
| return public.returnResult(status=False, msg=bk_result["msg"]) |
|
|
| |
| d_result = self.get_db_config_file(get) |
| if not d_result["status"]: |
| return public.returnResult(status=False, msg=d_result["msg"]) |
|
|
| |
| self.tar_path(get) |
|
|
| |
| self.backup_rewrite(get) |
|
|
| |
| self.get_site_permission(get) |
|
|
| |
| self.get_dir_list(get) |
|
|
| |
| self.update_package_conf(get) |
|
|
| |
| self.tar_package(get) |
|
|
| |
| self.update_database(get) |
|
|
| |
| last_config = { |
| "php_versions": get.php_versions, |
| "php_functions": get.php_functions, |
| "mysql_versions": get.mysql_versions, |
| "init_sql": get.init_sql, |
| "db_config_files": get.db_config_files, |
| "db_name": get.db_name, |
| "db_id": int(get.db_id) if get.db_id != "" else "", |
| } |
| cache.set(self.skey, last_config, 86400) |
|
|
| public.WriteLog("SITE_APP_PACKAGE", "创建一键应用环境包[{}]".format(get.app_name)) |
| public.set_module_logs('site_app_package', 'create', 1) |
|
|
| return public.returnResult(status=True, msg="打包成功") |
|
|
| |
| def delete(self, get): |
| ''' |
| @name 删除指定的应用包 |
| @param "data":{"参数名":""} <数据类型> 参数描述 |
| @return dict{"status":True/False,"msg":"提示信息"} |
| ''' |
| get.site_name = get.get("site_name/s", "") |
| if get.site_name == "": |
| return public.returnResult(status=False, msg="site_name不能为空") |
|
|
| get.app_name = get.get("app_name/s", "") |
| if get.app_name == "": |
| return public.returnResult(status=False, msg="app_name不能为空") |
|
|
| get.app_version = get.get("app_version/s", "") |
| if get.app_version == "": |
| return public.returnResult(status=False, msg="app_version不能为空") |
|
|
| find_version = public.M('app_package').where('site_name=? AND app_name=? AND app_version=?', |
| (get.site_name, get.app_name, get.app_version)).find() |
| if not find_version: |
| return public.returnResult(status=False, msg="应用包不存在") |
|
|
| public.ExecShell("rm -rf {}".format(find_version["package_path"])) |
|
|
| public.M('app_package').where('id=?', (find_version["id"],)).delete() |
| return public.returnResult(status=True, msg="删除成功") |
|
|
| |
| def get_db_all_result(self, get): |
| ''' |
| @name 返回指定网站的app_package表所有数据 |
| @author wzz <2024/5/9 上午10:42> |
| @param "data":{"参数名":""} <数据类型> 参数描述 |
| @return dict{"status":True/False,"msg":"提示信息"} |
| ''' |
| |
| return public.M('app_package').where("site_name=?", (get.site_name,)).order('app_version asc').select() |
|
|
| |
| def get_db_result(self, get): |
| ''' |
| @name 返回指定网站的app_package表的某条数据 |
| @author wzz <2024/5/9 上午11:03> |
| @param "data":{"参数名":""} <数据类型> 参数描述 |
| @return dict{"status":True/False,"msg":"提示信息"} |
| ''' |
| return public.M('app_package').where("site_name=? and app_name=? and app_version=?", (get.site_name, get.app_name, get.app_version)).find() |
|
|
| |
| def get_upload_db_all_result(self, get): |
| ''' |
| @name 返回上传数据库中所有的数据 |
| @author wzz <2024/5/9 下午5:15> |
| @param "data":{"参数名":""} <数据类型> 参数描述 |
| @return dict{"status":True/False,"msg":"提示信息"} |
| ''' |
| return public.M('app_package_upload').order('app_version asc').select() |
|
|
| |
| def get_upload_db_result(self, get): |
| ''' |
| @name 返回上传数据库中指定包的数据 |
| @author wzz <2024/5/9 下午5:19> |
| @param "data":{"参数名":""} <数据类型> 参数描述 |
| @return dict{"status":True/False,"msg":"提示信息"} |
| ''' |
| return public.M('app_package_upload').where("app_name=? and app_version=?", (get.app_name, get.app_version)).find() |
|
|
| |
| def get_list(self, get): |
| ''' |
| @name 获取所有的应用包列表 |
| @author wzz <2024/5/9 上午10:40> |
| @param "data":{"参数名":""} <数据类型> 参数描述 |
| @return dict{"status":True/False,"msg":"提示信息"} |
| ''' |
| get.site_name = get.get("site_name/s", "") |
| if get.site_name == "": |
| return public.returnResult(status=False, msg="site_name不能为空") |
|
|
| all_result = self.get_db_all_result(get) |
| for result in all_result: |
| result["status"] = True |
| result["info"] = "正常" |
| if not os.path.exists(result["package_path"]) or os.path.getsize(result["package_path"]) < 10: |
| result["status"] = False |
| result["info"] = "文件小于10B或压缩包不存在,请确认包是否正常,如果异常请删除重新创建!" |
|
|
| try: |
| result["db_config_file"] = json.loads(result["db_config_file"]) |
| except: |
| pass |
|
|
| try: |
| result["php_libs"] = json.loads(result["php_libs"]) |
| except: |
| pass |
|
|
| all_result.reverse() |
| public.set_module_logs('site_app_package', 'get_list', 1) |
| return public.returnResult(status=True, data=all_result) |
|
|
| |
| def get_package_conf(self, get): |
| ''' |
| @name 获取指定包中的package_conf |
| @author wzz <2024/5/9 上午11:18> |
| @param "data":{"参数名":""} <数据类型> 参数描述 |
| @return dict{"status":True/False,"msg":"提示信息"} |
| ''' |
| try: |
| get.package_info = json.loads(public.readFile(get.package_json_path)) |
| except: |
| get.package_info = {} |
|
|
| |
| def check_php_mysql(self, get): |
| ''' |
| @name 检查当前站点的php设置是否符合包要求的php |
| @author wzz <2024/5/9 下午3:10> |
| @param "data":{"参数名":""} <数据类型> 参数描述 |
| @return dict{"status":True/False,"msg":"提示信息"} |
| ''' |
| get.version = public.get_site_php_version(get.site_name) |
| if not get.version in get.package_info["php_versions"]: |
| return public.returnResult(status=False, msg="当前站点PHP版本[{}]不符合包要求的PHP版本[{}]".format( |
| get.version, |
| get.package_info["php_versions"] |
| )) |
|
|
| used_mysql = self.get_mysql_versions(get)["used"] |
| if get.package_info["mysql_versions"] != "00": |
| if not used_mysql in get.package_info["mysql_versions"]: |
| return public.returnResult(status=False, msg="当前站点MySQL版本[{}]不符合包要求的MySQL版本[{}]".format( |
| used_mysql, |
| get.package_info["mysql_versions"] |
| )) |
|
|
| return public.returnResult(status=True, msg="当前站点PHP和MySQL版本符合包要求") |
|
|
| |
| def set_php_disable(self, get): |
| ''' |
| @name 设置php函数到指定php版本 |
| @author wzz <2024/5/9 下午3:07> |
| @param "data":{"参数名":""} <数据类型> 参数描述 |
| @return dict{"status":True/False,"msg":"提示信息"} |
| ''' |
| if len(get.package_info["php_functions"]) != 0: |
| php_config = self.get_php_config(get) |
| get.disable_functions = php_config["data"]["disable_functions"] |
|
|
| p_disable_functions = get.package_info["php_functions"].split(",") |
| if len(p_disable_functions) != 0: |
| for p_disable_function in p_disable_functions: |
| if p_disable_function in get.disable_functions: |
| get.disable_functions = get.disable_functions.replace(p_disable_function + ",", "") |
|
|
| from config import config |
| c = config() |
| c.setPHPDisable(get) |
|
|
| |
| def install_phplib(self, get): |
| ''' |
| @name 安装php扩展到指定php版本 |
| @author wzz <2024/5/9 下午3:08> |
| @param "data":{"参数名":""} <数据类型> 参数描述 |
| @return dict{"status":True/False,"msg":"提示信息"} |
| ''' |
| if len(get.package_info["php_libs"]) != 0: |
| for lib_name in get.package_info["php_libs"]: |
| get.lib_name = lib_name["name"] |
| self.install_env_soft(get) |
|
|
| |
| def copy_site(self, get): |
| ''' |
| @name 从已经解压的应用包中找到网站文件,然后解压拷贝到指定网站目录 |
| @author wzz <2024/5/9 下午3:08> |
| @param "data":{"参数名":""} <数据类型> 参数描述 |
| @return dict{"status":True/False,"msg":"提示信息"} |
| ''' |
| public.ExecShell("cd {_temp_import_dir}/{app_name} && tar -zxvf {app_name}.tar.gz".format( |
| _temp_import_dir=self._temp_import_dir, |
| app_name=get.app_name, |
| )) |
| public.ExecShell("\cp -r {_temp_import_dir}/{app_name}/{app_name}/* {site_path}".format( |
| _temp_import_dir=self._temp_import_dir, |
| app_name=get.app_name, |
| site_path=get.site_info["path"], |
| )) |
|
|
| for dir_permission in get.package_info["dir_permission"].keys(): |
| if dir_permission == "root_permission": |
| get.path = get.site_info["path"] |
| if dir_permission == "run_permission": |
| if get.package_info["run_path"] == "/": |
| continue |
|
|
| get.path = os.path.join(get.site_info["path"], get.package_info["run_path"]) |
|
|
| get.permission = get.package_info["dir_permission"][dir_permission] |
| self.set_path_permission(get) |
|
|
| |
| self.set_dir_list_permission(get) |
|
|
| |
| def set_dir_list_permission(self, get): |
| ''' |
| @name 恢复网站目录下最多2层的文件和目录权限 |
| @param "data":{"参数名":""} <数据类型> 参数描述 |
| @return dict{"status":True/False,"msg":"提示信息"} |
| ''' |
| try: |
| dir_permission_list = json.loads(public.readFile("{}/dir_permission.json".format(self._backup_dir))) |
| except: |
| return |
|
|
| for dir_permission in dir_permission_list: |
| get.path = os.path.join(get.site_info["path"], dir_permission["path"]) |
| get.permission = dir_permission |
| self.set_path_permission(get) |
|
|
| |
| def copy_upload_site(self, get): |
| ''' |
| @name 从上传的应用包目录找到网站文件,然后解压拷贝到指定网站目录 |
| @author wzz <2024/5/9 下午5:52> |
| @param "data":{"参数名":""} <数据类型> 参数描述 |
| @return dict{"status":True/False,"msg":"提示信息"} |
| ''' |
| public.ExecShell("cd {upload_package_path} && tar -zxvf {app_name}.tar.gz".format( |
| upload_package_path=self._upload_package_path, |
| app_name=get.app_name, |
| )) |
| public.ExecShell("\cp -r {upload_package_path}/{app_name}/* {site_path}".format( |
| upload_package_path=self._upload_package_path, |
| app_name=get.app_name, |
| site_path=get.site_info["path"], |
| )) |
|
|
| for dir_permission in get.package_info["dir_permission"].keys(): |
| if dir_permission == "root_permission": |
| get.path = get.site_info["path"] |
| if dir_permission == "run_permission": |
| if get.package_info["run_path"] == "/": |
| continue |
|
|
| get.path = os.path.join(get.site_info["path"], get.package_info["run_path"]) |
|
|
| get.permission = get.package_info["dir_permission"][dir_permission] |
| self.set_path_permission(get) |
|
|
| |
| self.set_dir_list_permission(get) |
|
|
| |
| def import_init_sql(self, get): |
| ''' |
| @name 检查包json配置文件中的init_sql是否为1,如果是则执行查询网站关联的数据库并导入init.sql |
| @author wzz <2024/5/9 下午3:09> |
| @param "data":{"参数名":""} <数据类型> 参数描述 |
| @return dict{"status":True/False,"msg":"提示信息"} |
| ''' |
| if get.package_info["init_sql"] == 1: |
| get.db_info = public.M('databases').where('pid=?', (get.site_info['id'],)).find() |
| if get.db_info: |
| for db_conf in get.package_info["db_config_file"]: |
| db_conf = os.path.join(get.site_info["path"], db_conf) |
| if not os.path.exists(db_conf): |
| continue |
|
|
| conf_body = public.readFile(db_conf) |
| if not conf_body: |
| return public.returnResult(status=False, msg="{}内容为空".format(db_conf)) |
|
|
| conf_body = conf_body.replace(self.APP_PACKAGE_DB_USER, get.db_info["username"]) |
| conf_body = conf_body.replace(self.APP_PACKAGE_DB_NAME, get.db_info["name"]) |
| conf_body = conf_body.replace(self.APP_PACKAGE_DB_PASS, get.db_info["password"]) |
|
|
| public.writeFile(db_conf, conf_body) |
|
|
| from database import database |
| database = database() |
| get.file = "{}/{}/init.sql".format(self._temp_import_dir, get.app_name) |
| get.name = get.db_info["name"] |
| import_result = database.InputSql(get) |
| if not import_result["status"]: |
| return public.returnResult(status=False, msg=import_result["msg"]) |
|
|
| return public.returnResult(status=True, msg="导入init.sql成功") |
|
|
| return public.returnResult(status=True, msg="不需要导入") |
|
|
| |
| def import_upload_init_sql(self, get): |
| ''' |
| @name 检查指定上传包json配置文件中的init_sql是否为1,如果是则执行查询网站关联的数据库并导入init.sql |
| @author wzz <2024/5/9 下午6:08> |
| @param "data":{"参数名":""} <数据类型> 参数描述 |
| @return dict{"status":True/False,"msg":"提示信息"} |
| ''' |
| get.db_info = public.M('databases').where('pid=?', (get.site_info['id'],)).find() |
| if get.db_info: |
| if get.package_info["init_sql"] == 1: |
| from database import database |
| database = database() |
| get.file = "{}/init.sql".format(self._upload_package_path) |
| get.name = get.db_info["name"] |
| import_result = database.InputSql(get) |
| if not import_result["status"]: |
| return public.returnResult(status=False, msg=import_result["msg"]) |
|
|
| for db_conf in get.package_info["db_config_file"]: |
| sample_db_conf = "" |
| if "sample" in db_conf: |
| sample_db_conf = db_conf.replace("sample_", "").replace("_sample", "").replace("-sample", "").replace("sample-", "").replace(".sample", "").replace("sample.", "").replace("sample", "") |
| db_conf = db_conf.replace("sample_", "").replace("_sample", "").replace("-sample", "").replace("sample-", "").replace(".sample", "").replace("sample.", "").replace("sample", "") |
|
|
| if sample_db_conf != "": |
| sample_db_conf = os.path.join(get.site_info["path"], sample_db_conf) |
| if os.path.exists(sample_db_conf): |
| conf_body = public.readFile(sample_db_conf) |
| if conf_body: |
| conf_body = conf_body.replace(self.APP_PACKAGE_DB_USER, get.db_info["username"]) |
| conf_body = conf_body.replace(self.APP_PACKAGE_DB_NAME, get.db_info["name"]) |
| conf_body = conf_body.replace(self.APP_PACKAGE_DB_PASS, get.db_info["password"]) |
|
|
| public.writeFile(sample_db_conf, conf_body) |
|
|
| db_conf = os.path.join(get.site_info["path"], db_conf) |
| if not os.path.exists(db_conf): |
| public.ExecShell("cp -f {} {}".format(sample_db_conf, db_conf)) |
|
|
| conf_body = public.readFile(db_conf) |
| if not conf_body: |
| return public.returnResult(status=False, msg="{}内容为空".format(db_conf)) |
|
|
| conf_body = conf_body.replace(self.APP_PACKAGE_DB_USER, get.db_info["username"]) |
| conf_body = conf_body.replace(self.APP_PACKAGE_DB_NAME, get.db_info["name"]) |
| conf_body = conf_body.replace(self.APP_PACKAGE_DB_PASS, get.db_info["password"]) |
|
|
| public.writeFile(db_conf, conf_body) |
| else: |
| db_conf = os.path.join(get.site_info["path"], db_conf) |
| if not os.path.exists(db_conf): |
| continue |
|
|
| conf_body = public.readFile(db_conf) |
| if not conf_body: |
| return public.returnResult(status=False, msg="{}内容为空".format(db_conf)) |
|
|
| conf_body = conf_body.replace(self.APP_PACKAGE_DB_USER, get.db_info["username"]) |
| conf_body = conf_body.replace(self.APP_PACKAGE_DB_NAME, get.db_info["name"]) |
| conf_body = conf_body.replace(self.APP_PACKAGE_DB_PASS, get.db_info["password"]) |
|
|
| public.writeFile(db_conf, conf_body) |
|
|
| return public.returnResult(status=True, msg="导入init.sql成功") |
|
|
| |
| def apply_site(self, get): |
| ''' |
| @name 应用指定的应用环境包到指定网站 |
| @author wzz <2024/5/9 上午10:55> |
| @param "data":{"参数名":""} <数据类型> 参数描述 |
| @return dict{"status":True/False,"msg":"提示信息"} |
| ''' |
| get.site_name = get.get("site_name/s", "") |
| if get.site_name == "": |
| return public.returnResult(status=False, msg="site_name不能为空") |
|
|
| get.app_name = get.get("app_name/s", "") |
| if get.app_name == "": |
| return public.returnResult(status=False, msg="app_name不能为空") |
|
|
| get.app_version = get.get("app_version/s", "") |
| if get.app_version == "": |
| return public.returnResult(status=False, msg="app_version不能为空") |
|
|
| get.site_info = public.M('sites').where('name=?', (get.site_name,)).find() |
| if not get.site_info: |
| return public.returnResult(status=False, msg="获取网站信息失败") |
|
|
| get.package_info = self.get_db_result(get) |
| if not get.package_info: |
| return public.returnResult(status=False, msg="获取应用包信息失败") |
|
|
| if not os.path.exists(get.package_info["package_path"]): |
| return public.returnResult(status=False, msg="应用包不存在") |
|
|
| |
| self._temp_import_dir = os.path.join(self._temp_backup_dir, "import") |
| if os.path.exists(self._temp_import_dir): |
| public.ExecShell("rm -rf {}".format(self._temp_import_dir)) |
| public.ExecShell("mkdir -p {}".format(self._temp_import_dir)) |
|
|
| |
| public.ExecShell("tar -zxvf {} -C {}".format(get.package_info["package_path"], self._temp_import_dir)) |
|
|
| |
| get.package_json_path = "{_temp_import_dir}/{app_name}/package.json".format( |
| _temp_import_dir=self._temp_import_dir, |
| app_name=get.app_name, |
| ) |
|
|
| self.get_package_conf(get) |
| if not get.package_info: |
| return public.returnResult(status=False, msg="包异常,获取package.json配置文件失败") |
|
|
| |
| check_result = self.check_php_mysql(get) |
| if not check_result["status"]: |
| return public.returnResult(status=False, msg=check_result["msg"]) |
|
|
| |
| self.set_php_disable(get) |
| |
| self.install_phplib(get) |
| |
| self.restore_rewrite(get) |
| |
| self.copy_site(get) |
| |
| import_result = self.import_init_sql(get) |
| if not import_result["status"]: |
| return public.returnResult(status=False, msg=import_result["msg"]) |
|
|
| public.set_module_logs('site_app_package', 'apply_site', 1) |
| return public.returnResult(status=True, msg="应用成功") |
|
|
| |
| def upload_package(self, get): |
| ''' |
| @name 上传应用包到指定位置 |
| @author wzz <2024/5/9 下午3:51> |
| @param "data":{"参数名":""} <数据类型> 参数描述 |
| @return dict{"status":True/False,"msg":"提示信息"} |
| ''' |
| if not os.path.exists(self._temp_upload_package_dir): |
| public.ExecShell("mkdir -p {}".format(self._temp_upload_package_dir)) |
|
|
| get.f_path = get.get("f_path/s", "") |
| get.f_name = get.get("f_name/s", "") |
| get.f_size = get.get("f_size/s", "") |
| get.f_start = get.get("f_start/s", "") |
| get.blob = get.get("blob/s", "") |
|
|
| from files import files |
| fileObj = files() |
| upload_result = fileObj.upload(get) |
| if type(upload_result) == dict and not upload_result["status"]: |
| return public.returnResult(status=False, msg=upload_result["msg"]) |
|
|
| get.size = os.path.getsize(os.path.join(self._temp_upload_package_dir, get.f_name)) |
|
|
| if get.size != int(get.f_size): |
| return public.returnResult(status=False, msg="上传文件大小不一致,上传失败!") |
|
|
| |
| public.ExecShell("tar -zxvf {}/{} -C {}".format(self._temp_upload_package_dir, get.f_name, self._upload_package_dir)) |
|
|
| |
| get.app_name = get.f_name.split("_v")[0] |
| |
| get.package_json_path = "{_upload_package_dir}/{app_name}/package.json".format( |
| _upload_package_dir=self._upload_package_dir, |
| app_name=get.app_name, |
| ) |
|
|
| self.get_package_conf(get) |
| if not get.package_info: |
| public.ExecShell("rm -rf {}".format(os.path.join(self._temp_upload_package_dir, get.f_name))) |
| public.ExecShell("rm -rf {}".format(os.path.join(self._upload_package_dir, get.app_name))) |
| return public.returnResult(status=False, msg="应用包异常,获取package.json配置文件失败") |
|
|
| |
| self.update_upload_database(get) |
|
|
| public.set_module_logs('site_app_package', 'upload_package', 1) |
| return public.returnResult(status=True, msg="上传成功") |
|
|
| |
| def get_upload_list(self, get): |
| ''' |
| @name 获取上传列表的所有包数据 |
| @author wzz <2024/5/9 下午5:13> |
| @param "data":{"参数名":""} <数据类型> 参数描述 |
| @return dict{"status":True/False,"msg":"提示信息"} |
| ''' |
| all_result = self.get_upload_db_all_result(get) |
| for result in all_result: |
| result["status"] = True |
| result["info"] = "正常" |
| if not os.path.exists(result["package_path"]) or os.path.getsize(result["package_path"]) < 10: |
| result["status"] = False |
| result["info"] = "文件小于10B或压缩包不存在,请确认包是否正常,如果异常请删除重新创建!" |
|
|
| try: |
| result["db_config_file"] = json.loads(result["db_config_file"]) |
| except: |
| pass |
|
|
| try: |
| result["php_libs"] = json.loads(result["php_libs"]) |
| except: |
| pass |
|
|
| all_result.reverse() |
|
|
| public.set_module_logs('site_app_package', 'get_upload_list', 1) |
| return public.returnResult(status=True, data=all_result) |
|
|
| |
| def delete_upload(self, get): |
| ''' |
| @name 删除指定的上传包 |
| @param "data":{"参数名":""} <数据类型> 参数描述 |
| @return dict{"status":True/False,"msg":"提示信息"} |
| ''' |
| get.app_name = get.get("app_name/s", "") |
| if get.app_name == "": |
| return public.returnResult(status=False, msg="app_name不能为空") |
|
|
| get.app_version = get.get("app_version/s", "") |
| if get.app_version == "": |
| return public.returnResult(status=False, msg="app_version不能为空") |
|
|
| find_version = public.M('app_package_upload').where('app_name=? AND app_version=?', |
| (get.app_name, get.app_version)).find() |
| if not find_version: |
| return public.returnResult(status=False, msg="应用包不存在") |
|
|
| public.ExecShell("rm -rf {}".format(find_version["package_path"])) |
|
|
| public.M('app_package_upload').where('id=?', (find_version["id"],)).delete() |
| return public.returnResult(status=True, msg="删除成功") |
|
|
| |
| def get_upload_result(self, get): |
| ''' |
| @name 获取上传列表中某一个包的数据 |
| @author wzz <2024/5/9 下午6:33> |
| @param "data":{"参数名":""} <数据类型> 参数描述 |
| @return dict{"sbt 2 |
| tatus":True/False,"msg":"提示信息"} |
| ''' |
| get.app_name = get.get("app_name/s", "") |
| if get.app_name == "": |
| return public.returnResult(status=False, msg="app_name不能为空") |
|
|
| get.app_version = get.get("app_version/s", "") |
| if get.app_version == "": |
| return public.returnResult(status=False, msg="app_version不能为空") |
|
|
| installed_phps = [] |
| for v in self._php_versions: |
| if os.path.exists(public.get_setup_path() + "/php/" + v + "/bin/php"): |
| installed_phps.append(v) |
|
|
| result = self.get_upload_db_result(get) |
| result["installed_phps"] = installed_phps |
| result["installed_mysql"] = self.get_mysql_versions(get)["used"] |
|
|
| result["status"] = True |
| result["info"] = "正常" |
| if not os.path.exists(result["package_path"]) or os.path.getsize(result["package_path"]) < 10: |
| result["status"] = False |
| result["info"] = "文件小于10B或压缩包不存在,请确认包是否正常,如果异常请删除重新创建!" |
|
|
| try: |
| result["db_config_file"] = json.loads(result["db_config_file"]) |
| except: |
| pass |
|
|
| try: |
| result["php_libs"] = json.loads(result["php_libs"]) |
| except: |
| pass |
|
|
| return public.returnResult(status=True, data=result) |
|
|
| |
| def create_site(self, get): |
| ''' |
| @name 创建网站并应用应用包到指定网站中,如果网站已经存在则直接应用应用包到指定网站中,如果网站不存在则创建网站并应用应用包到指定网站中 |
| @param "data":{"参数名":""} <数据类型> 参数描述 |
| @return dict{"status":True/False,"msg":"提示信息"} |
| ''' |
| get.site_name = get.get("site_name/s", "") |
| if get.site_name == "": |
| return public.returnResult(status=False, msg="site_name不能为空") |
|
|
| get.port = "80" |
| if ":" in get.site_name: |
| get.port = get.site_name.split(":")[1] |
| get.site_name = get.site_name.split(":")[0] |
|
|
| get.webname = get.get("webname", "") |
| if get.webname == "": |
| return public.returnResult(status=False, msg="webname不能为空") |
|
|
| get.app_name = get.get("app_name/s", "") |
| if get.app_name == "": |
| return public.returnResult(status=False, msg="app_name不能为空") |
|
|
| get.app_version = get.get("app_version/s", "") |
| if get.app_version == "": |
| return public.returnResult(status=False, msg="app_version不能为空") |
|
|
| get.ps = get.get("ps/s", "") |
| get.ps = public.xssencode2(get.ps) |
|
|
| |
| get.package_json_path = "{_upload_package_dir}/{app_name}/package.json".format( |
| _upload_package_dir=self._upload_package_dir, |
| app_name=get.app_name, |
| ) |
|
|
| self.get_package_conf(get) |
| if not get.package_info: |
| return public.returnResult(status=False, msg="包异常,获取package.json配置文件失败") |
|
|
| self._upload_package_path = self._upload_package_path.format(app_name=get.app_name) |
|
|
| |
| get.php_list = get.package_info["php_versions"].split(",") |
| get.php_list.sort() |
| get.php_list.reverse() |
| for php_version in get.php_list: |
| if os.path.exists(public.get_setup_path() + "/php/" + php_version + "/bin/php"): |
| get.php_version = php_version |
| break |
|
|
| from panelSite import panelSite |
| tmp_args = { |
| 'webname': get.webname, |
| 'type': 'PHP', |
| 'port': get.port, |
| 'ps': get.ps, |
| 'path': os.path.join("/www/wwwroot", get.site_name), |
| 'type_id': 0, |
| 'version': get.php_version, |
| 'ftp': False, |
| 'sql': False, |
| } |
| if get.package_info["db_config_file"]: |
| tmp_args["sql"] = "MySQL" |
| tmp_args["codeing"] = get.package_info["db_character"] if get.package_info["db_character"] != "" else "utf8mb4" |
| tmp_args["datauser"] = get.site_name.replace(".", "_") |
| tmp_args["datapassword"] = public.GetRandomString(16) |
|
|
| args = public.to_dict_obj(tmp_args) |
| add_site_result = panelSite().AddSite(args) |
| if "status" in add_site_result and not add_site_result["status"]: |
| return public.returnResult(status=False, msg=add_site_result["msg"]) |
| if not add_site_result["siteStatus"]: |
| return public.returnResult(status=False, msg="创建网站失败") |
|
|
| get.site_info = public.M('sites').where('name=?', (get.site_name,)).find() |
| if not get.site_info: |
| return public.returnResult(status=False, msg="获取网站信息失败") |
|
|
| get.version = public.get_site_php_version(get.site_name) |
| if not get.version in get.package_info["php_versions"]: |
| return public.returnResult(status=False, msg="当前站点PHP版本[{}]不符合包要求的PHP版本[{}]".format( |
| get.version, |
| get.package_info["php_versions"] |
| )) |
|
|
| |
| self.set_php_disable(get) |
| |
| self.install_phplib(get) |
| |
| self.restore_upload_rewrite(get) |
| |
| self.copy_upload_site(get) |
| |
| import_result = self.import_upload_init_sql(get) |
|
|
| if not import_result["status"]: |
| return public.returnResult(status=False, msg=import_result["msg"]) |
|
|
| success_url = "http://{}".format(get.site_name) |
| if "success_url" in get.package_info: |
| success_url = success_url + get.package_info["success_url"] |
|
|
| add_site_result["success_url"] = success_url |
|
|
| public.set_module_logs('site_app_package', 'create_site', 1) |
| return public.returnResult(status=True, msg="网站创建成功", data=add_site_result) |
|
|