Files
2026-04-07 02:04:22 +05:30

186 lines
7.3 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# coding: utf-8
# -------------------------------------------------------------------
# YakPanel
# -------------------------------------------------------------------
# Copyright (c) 2015-2099 YakPanel(www.yakpanel.com) All rights reserved.
# -------------------------------------------------------------------
# Author: wzz <wzz@yakpanel.com>
# -------------------------------------------------------------------
import os
import time
import traceback
import gettext
_ = gettext.gettext
# ------------------------------
# Docker模型
# ------------------------------
import public
from btdockerModelV2 import containerModel as dc
from btdockerModelV2 import dk_public as dp
from btdockerModelV2.dockerBase import dockerBase
from public.validate import Param
class main(dockerBase):
# 2023/12/22 上午 9:56 备份指定容器的mount volume
def backup_volume(self, get):
'''
@name 备份指定容器的mount volume
@author wzz <2023/12/22 上午 11:19>
@param "data":{"container_id":"容器ID"}
@return dict{"status":True/False,"msg":"提示信息"}
'''
# 校验参数
try:
get.validate([
Param('container_id').Require().String(),
], [
public.validate.trim_filter(),
])
except Exception as ex:
public.print_log("error info: {}".format(ex))
return public.return_message(-1, 0, str(ex))
try:
client = dp.docker_client()
container = client.containers.get(get.container_id)
volume_list = container.attrs["Mounts"]
volume_list = [v["Source"] for v in volume_list]
if not volume_list:
return public.return_message(-1, 0,
public.lang("There is no volume to back up"))
backup_path = "/www/backup/btdocker/volumes/{}".format(container.name)
if not os.path.exists(backup_path):
os.makedirs(backup_path, 0o755)
import subprocess
public.ExecShell("echo -n > {}".format(self._backup_log))
for v in volume_list:
backup_name = os.path.basename(v)
# 2023/12/22 上午 10:34 每个压缩包命名都用v的目录名如果是文件则用文件名
tar_name = "{}_{}_{}.tar.gz".format(
container.name,
backup_name,
time.strftime("%Y%m%d_%H%M%S", time.localtime())
)
backup_file = os.path.join(backup_path, tar_name)
source_path = os.path.dirname(v)
cmd = "cd {} && tar zcvf {} {}".format(source_path, backup_file, backup_name)
cmd = ("nohup echo 'To start backing up {} of container {}, it may take more than 1-5 minutes...' >> {};"
"{} >> {} 2>&1 &&"
"echo 'bt_successful' >> {} || echo 'bt_failed' >> {} &"
.format(
container.name,
tar_name,
self._backup_log,
cmd,
self._backup_log,
self._backup_log,
self._backup_log,
))
subprocess.Popen(cmd, shell=True)
# 2023/12/22 下午 12:17 添加到数据库
dp.sql('dk_backup').add(
'type,name,container_id,container_name,filename,size,addtime',
(3, tar_name, container.id, container.name, backup_file, 0, time.strftime(
"%Y-%m-%d %H:%M:%S", time.localtime()
))
)
public.WriteLog("Docker module", "The {} of the backup container {} succeeds".format(container.name, tar_name))
return public.return_message(0, 0, public.lang("The backup task was created successfully."))
except Exception as e:
print(traceback.format_exc())
return public.return_message(-1, 0, public.lang("Failed to create a backup task {}", str(e)))
# 2023/12/22 上午 11:23 获取指定容器的备份列表
def get_backup_list(self, get):
'''
@name 获取指定容器的备份列表
@param "data":{"container_id":"容器ID"}
@return list[dict{"":""}]
'''
# 校验参数
try:
get.validate([
Param('container_id').Require().String(),
], [
public.validate.trim_filter(),
])
except Exception as ex:
public.print_log("error info: {}".format(ex))
return public.return_message(-1, 0, str(ex))
try:
# 2023/12/22 下午 12:24 从数据库中获取已备份的指定容器
backup_list = dp.sql('dk_backup').where('container_id=?', (get.container_id,)).field(
'name,container_id,container_name,filename,size,addtime'
).select()
for l in backup_list:
if not os.path.exists(l['filename']):
l['size'] = 0
l['ps'] = 'file does not exist'
continue
l['size'] = os.path.getsize(l['filename'])
l['ps'] = 'local backup'
return public.return_message(0, 0, backup_list)
except Exception as e:
print(traceback.format_exc())
return public.return_message(0, 0, [])
# 2023/12/22 下午 2:25 删除指定容器的备份
def remove_backup(self, get):
'''
@name 删除指定容器的备份
@param "data":{"container_id":"容器ID","container_name":"容器名","name":"文件名"}
@return dict{"status":True/False,"msg":"提示信息"}
'''
# 校验参数
try:
get.validate([
Param('container_id').Require().String(),
Param('container_name').Require().String(),
Param('name').Require().String(),
], [
public.validate.trim_filter(),
])
except Exception as ex:
public.print_log("error info: {}".format(ex))
return public.return_message(-1, 0, str(ex))
try:
# 2023/12/22 下午 2:26 从数据库中删除指定容器的备份
dp.sql('dk_backup').where('container_id=? and name=?', (get.container_id, get.name)).delete()
# 2023/12/22 下午 2:27 删除本地备份文件
backup_path = "/www/backup/btdocker/volumes/{}".format(get.container_name)
file_path = os.path.join(backup_path, get.name)
if not os.path.exists(file_path):
return public.return_message(0, 0, public.lang("successfully delete"))
os.remove(file_path)
return public.return_message(0, 0, public.lang("successfully delete"))
except Exception as e:
print(traceback.format_exc())
return public.return_message(-1, 0, public.lang("Failed to delete the file, reason: {}", get.name, str(e)))
def get_pull_log(self, get):
"""
获取镜像拉取日志websocket
@param get:
@return:
"""
get.wsLogTitle = "Start container directory backup, please wait..."
get._log_path = self._backup_log
return self.get_ws_log(get)