Files
yakpanel-core/class/public/mysqlmgr.py

137 lines
6.0 KiB
Python
Raw Normal View History

2026-04-07 02:04:22 +05:30
# MySQL管理公共模块
# @author Zhj<2024/07/01>
import os
import json
import time
import typing
from .common import M, aap_t_simple_result, aap_t_mysql_dump_info, to_dict_obj, get_msg_gettext, get_mysqldump_bin, MysqlConn, get_database_character, ExecShell
from .exceptions import HintException
# 备份MySQL数据库
def backup(database_id: int) -> aap_t_simple_result:
from database_v2 import database
data = database().ToBackup(to_dict_obj({'id': database_id}))
if int(data.get('status', 0)) != 0:
return aap_t_simple_result(False, data.get('message', {})['result'])
return aap_t_simple_result(True, M('backup').where('type = 1 and pid=?', (database_id,)).order('id desc').getField('filename'))
# 还原MySQL数据库
def restore(db_name: str, bak_file: str) -> aap_t_simple_result:
from database_v2 import database
data = database().InputSql(to_dict_obj({'name': db_name, 'file': bak_file}))
return aap_t_simple_result(int(data.get('status', 0)) == 0, data.get('message', {})['result'])
# 删除MySQL数据库备份文件
def del_bak(bak_file: str) -> aap_t_simple_result:
# yakpanel内部备份
bak_id_dict = M('backup').where('`type`=1 and `filename`=?', (bak_file,)).field('id').find()
if isinstance(bak_id_dict, dict):
from database_v2 import database
data = database().DelBackup(to_dict_obj({'id': int(bak_id_dict['id'])}))
return aap_t_simple_result(int(data.get('status', 0)) == 0, data.get('message', {})['result'])
# 其它途径备份
if not os.path.exists(bak_file):
return aap_t_simple_result(False, get_msg_gettext('File not exists'))
os.remove(bak_file)
return aap_t_simple_result(True, get_msg_gettext('Remove backup successfully'))
# 数据库导出
def dumpsql_with_aap(database_id: int, backup_path: typing.Optional[str] = None) -> aap_t_mysql_dump_info:
import shlex
db_find = M('databases').where("id=?", (database_id,)).find()
if not isinstance(db_find, dict):
raise HintException(get_msg_gettext('Table {} has been corrupted', ('databases',)))
if backup_path is None:
backup_path_tmp = M('config').order('`id` desc').limit(1).field('backup_path').find()
if not isinstance(backup_path_tmp, dict):
raise HintException(get_msg_gettext('Table {} has been corrupted', ('config',)))
backup_path = os.path.join(str(backup_path_tmp['backup_path']), 'database')
name = db_find['name']
fileName = name + '_' + time.strftime('%Y%m%d_%H%M%S', time.localtime()) + '.sql.gz'
backupName = os.path.join(backup_path, fileName)
mysqldump_bin = get_mysqldump_bin()
from database_v2 import database
database_obj = database()
if db_find['db_type'] in ['0', 0]:
# 本地数据库
# 测试数据库连接
with MysqlConn() as conn:
conn.execute("show databases")
root = M('config').where('id=?', (1,)).getField('mysql_root')
if not os.path.exists(backup_path):
os.makedirs(backup_path, 0o600)
if not database_obj.mypass(True, root):
raise HintException(get_msg_gettext("Database configuration file failed to get checked, please check "
"if MySQL configuration file exists [/etc/my.cnf]"))
try:
password = M('config').where('id=?', (1,)).getField('mysql_root')
if not password:
raise HintException(get_msg_gettext("Database password cannot be empty"))
password = shlex.quote(str(password))
os.environ["MYSQL_PWD"] = password
ExecShell(mysqldump_bin + " -R -E --triggers=false --default-character-set=" + get_database_character(name) + " --force --opt \"" + name + "\" -u root -p" + password + " | gzip > " + backupName)
finally:
os.environ["MYSQL_PWD"] = ""
database_obj.mypass(False, root)
elif db_find['db_type'] in ['1', 1]:
# 远程数据库
try:
conn_config = json.loads(db_find['conn_config'])
res = database_obj.CheckCloudDatabase(conn_config)
if isinstance(res, dict):
raise HintException(res.get('msg', get_msg_gettext('Cannot connect to remote MySQL')))
password = shlex.quote(str(conn_config['db_password']))
os.environ["MYSQL_PWD"] = password
ExecShell(mysqldump_bin + " -h " + conn_config['db_host'] + " -P " + str(int(conn_config['db_port'])) + " -R -E --triggers=false --default-character-set=" + get_database_character(name) + " --force --opt \"" + str(db_find['name']) + "\" -u " + str(conn_config['db_user']) + " -p" + password + " | gzip > " + backupName)
finally:
os.environ["MYSQL_PWD"] = ""
elif db_find['db_type'] in ['2', 2]:
try:
conn_config = M('database_servers').where('id=?', db_find['sid']).find()
res = database_obj.CheckCloudDatabase(conn_config)
if isinstance(res, dict):
raise HintException(res.get('msg', get_msg_gettext('Cannot connect to remote MySQL')))
password = shlex.quote(str(conn_config['db_password']))
os.environ["MYSQL_PWD"] = password
ExecShell(mysqldump_bin + " -h " + conn_config['db_host'] + " -P " + str(int(conn_config['db_port'])) + " -R -E --triggers=false --default-character-set=" + get_database_character(name) + " --force --opt \"" + str(db_find['name']) + "\" -u " + str(conn_config['db_user']) + " -p" + str(conn_config['db_password']) + " | gzip > " + backupName)
finally:
os.environ["MYSQL_PWD"] = ""
else:
raise HintException(get_msg_gettext("Unsupported database type"))
if not os.path.exists(backupName):
raise HintException(get_msg_gettext("Backup error"))
# # 将备份信息添加到数据库中
# bak_id = M('backup').add('type,name,pid,filename,size,addtime', (1, fileName, id, backupName, 0, time.strftime('%Y-%m-%d %X', time.localtime())))
return aap_t_mysql_dump_info(db_name=str(db_find['name']), file=backupName, dump_time=int(time.time()))