mirror of
https://github.com/jxxghp/MoviePilot.git
synced 2026-08-28 19:47:41 +08:00
add Docker Client API地址
This commit is contained in:
@@ -395,10 +395,6 @@ def save_plugin_folders(folders: dict, _: schemas.TokenPayload = Depends(get_cur
|
|||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
SystemConfigOper().set(SystemConfigKey.PluginFolders, folders)
|
SystemConfigOper().set(SystemConfigKey.PluginFolders, folders)
|
||||||
|
|
||||||
# 验证保存结果
|
|
||||||
saved_result = SystemConfigOper().get(SystemConfigKey.PluginFolders)
|
|
||||||
|
|
||||||
return schemas.Response(success=True)
|
return schemas.Response(success=True)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"[文件夹API] 保存文件夹配置失败: {str(e)}")
|
logger.error(f"[文件夹API] 保存文件夹配置失败: {str(e)}")
|
||||||
|
|||||||
@@ -36,8 +36,8 @@ from app.schemas.types import SystemConfigKey
|
|||||||
from app.utils.crypto import HashUtils
|
from app.utils.crypto import HashUtils
|
||||||
from app.utils.http import RequestUtils
|
from app.utils.http import RequestUtils
|
||||||
from app.utils.security import SecurityUtils
|
from app.utils.security import SecurityUtils
|
||||||
from app.utils.system import SystemUtils
|
|
||||||
from app.utils.url import UrlUtils
|
from app.utils.url import UrlUtils
|
||||||
|
from helper.system import SystemHelper
|
||||||
from version import APP_VERSION
|
from version import APP_VERSION
|
||||||
|
|
||||||
router = APIRouter()
|
router = APIRouter()
|
||||||
@@ -474,12 +474,12 @@ def restart_system(_: User = Depends(get_current_active_superuser)):
|
|||||||
"""
|
"""
|
||||||
重启系统(仅管理员)
|
重启系统(仅管理员)
|
||||||
"""
|
"""
|
||||||
if not SystemUtils.can_restart():
|
if not SystemHelper.can_restart():
|
||||||
return schemas.Response(success=False, message="当前运行环境不支持重启操作!")
|
return schemas.Response(success=False, message="当前运行环境不支持重启操作!")
|
||||||
# 标识停止事件
|
# 标识停止事件
|
||||||
global_vars.stop_system()
|
global_vars.stop_system()
|
||||||
# 执行重启
|
# 执行重启
|
||||||
ret, msg = SystemUtils.restart()
|
ret, msg = SystemHelper.restart()
|
||||||
return schemas.Response(success=ret, message=msg)
|
return schemas.Response(success=ret, message=msg)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+3
-1
@@ -10,6 +10,7 @@ from app.schemas import Notification, MessageChannel
|
|||||||
from app.utils.http import RequestUtils
|
from app.utils.http import RequestUtils
|
||||||
from app.utils.singleton import Singleton
|
from app.utils.singleton import Singleton
|
||||||
from app.utils.system import SystemUtils
|
from app.utils.system import SystemUtils
|
||||||
|
from helper.system import SystemHelper
|
||||||
from version import FRONTEND_VERSION, APP_VERSION
|
from version import FRONTEND_VERSION, APP_VERSION
|
||||||
|
|
||||||
|
|
||||||
@@ -45,7 +46,8 @@ class SystemChain(ChainBase, metaclass=Singleton):
|
|||||||
"channel": channel.value,
|
"channel": channel.value,
|
||||||
"userid": userid
|
"userid": userid
|
||||||
}, self._restart_file)
|
}, self._restart_file)
|
||||||
SystemUtils.restart()
|
# 重启
|
||||||
|
SystemHelper.restart()
|
||||||
|
|
||||||
def __get_version_message(self) -> str:
|
def __get_version_message(self) -> str:
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -280,6 +280,8 @@ class ConfigModel(BaseModel):
|
|||||||
TOKENIZED_SEARCH: bool = False
|
TOKENIZED_SEARCH: bool = False
|
||||||
# 为指定默认字幕添加.default后缀
|
# 为指定默认字幕添加.default后缀
|
||||||
DEFAULT_SUB: Optional[str] = "zh-cn"
|
DEFAULT_SUB: Optional[str] = "zh-cn"
|
||||||
|
# Docker Client API地址
|
||||||
|
DOCKER_CLIENT_API: Optional[str] = "tcp://127.0.0.1:38379"
|
||||||
|
|
||||||
|
|
||||||
class Settings(BaseSettings, ConfigModel, LogConfigModel):
|
class Settings(BaseSettings, ConfigModel, LogConfigModel):
|
||||||
|
|||||||
+68
-67
@@ -8,6 +8,7 @@ from app.utils.http import RequestUtils
|
|||||||
from app.utils.singleton import Singleton
|
from app.utils.singleton import Singleton
|
||||||
from app.utils.string import StringUtils
|
from app.utils.string import StringUtils
|
||||||
from app.utils.system import SystemUtils
|
from app.utils.system import SystemUtils
|
||||||
|
from helper.system import SystemHelper
|
||||||
|
|
||||||
|
|
||||||
class ResourceHelper(metaclass=Singleton):
|
class ResourceHelper(metaclass=Singleton):
|
||||||
@@ -32,80 +33,80 @@ class ResourceHelper(metaclass=Singleton):
|
|||||||
检测是否有更新,如有则下载安装
|
检测是否有更新,如有则下载安装
|
||||||
"""
|
"""
|
||||||
if not settings.AUTO_UPDATE_RESOURCE:
|
if not settings.AUTO_UPDATE_RESOURCE:
|
||||||
return
|
return None
|
||||||
if SystemUtils.is_frozen():
|
if SystemUtils.is_frozen():
|
||||||
return
|
return None
|
||||||
logger.info("开始检测资源包版本...")
|
logger.info("开始检测资源包版本...")
|
||||||
res = RequestUtils(proxies=self.proxies, headers=settings.GITHUB_HEADERS, timeout=10).get_res(self._repo)
|
res = RequestUtils(proxies=self.proxies, headers=settings.GITHUB_HEADERS, timeout=10).get_res(self._repo)
|
||||||
if res:
|
if res:
|
||||||
try:
|
try:
|
||||||
resource_info = json.loads(res.text)
|
resource_info = json.loads(res.text)
|
||||||
|
online_version = resource_info.get("version")
|
||||||
|
if online_version:
|
||||||
|
logger.info(f"最新资源包版本:v{online_version}")
|
||||||
|
# 需要更新的资源包
|
||||||
|
need_updates = {}
|
||||||
|
# 资源明细
|
||||||
|
resources: dict = resource_info.get("resources") or {}
|
||||||
|
for rname, resource in resources.items():
|
||||||
|
rtype = resource.get("type")
|
||||||
|
platform = resource.get("platform")
|
||||||
|
target = resource.get("target")
|
||||||
|
version = resource.get("version")
|
||||||
|
# 判断平台
|
||||||
|
if platform and platform != SystemUtils.platform():
|
||||||
|
continue
|
||||||
|
# 判断版本号
|
||||||
|
if rtype == "auth":
|
||||||
|
# 站点认证资源
|
||||||
|
local_version = self.siteshelper.auth_version
|
||||||
|
elif rtype == "sites":
|
||||||
|
# 站点索引资源
|
||||||
|
local_version = self.siteshelper.indexer_version
|
||||||
|
else:
|
||||||
|
continue
|
||||||
|
if StringUtils.compare_version(version, ">", local_version):
|
||||||
|
logger.info(f"{rname} 资源包有更新,最新版本:v{version}")
|
||||||
|
else:
|
||||||
|
continue
|
||||||
|
# 需要安装
|
||||||
|
need_updates[rname] = target
|
||||||
|
if need_updates:
|
||||||
|
# 下载文件信息列表
|
||||||
|
r = RequestUtils(proxies=settings.PROXY, headers=settings.GITHUB_HEADERS,
|
||||||
|
timeout=30).get_res(self._files_api)
|
||||||
|
if r and not r.ok:
|
||||||
|
return None, f"连接仓库失败:{r.status_code} - {r.reason}"
|
||||||
|
elif not r:
|
||||||
|
return None, "连接仓库失败"
|
||||||
|
files_info = r.json()
|
||||||
|
for item in files_info:
|
||||||
|
save_path = need_updates.get(item.get("name"))
|
||||||
|
if not save_path:
|
||||||
|
continue
|
||||||
|
if item.get("download_url"):
|
||||||
|
logger.info(f"开始更新资源文件:{item.get('name')} ...")
|
||||||
|
download_url = f"{settings.GITHUB_PROXY}{item.get('download_url')}"
|
||||||
|
# 下载资源文件
|
||||||
|
res = RequestUtils(proxies=self.proxies, headers=settings.GITHUB_HEADERS,
|
||||||
|
timeout=180).get_res(download_url)
|
||||||
|
if not res:
|
||||||
|
logger.error(f"文件 {item.get('name')} 下载失败!")
|
||||||
|
elif res.status_code != 200:
|
||||||
|
logger.error(f"下载文件 {item.get('name')} 失败:{res.status_code} - {res.reason}")
|
||||||
|
# 创建插件文件夹
|
||||||
|
file_path = self._base_dir / save_path / item.get("name")
|
||||||
|
if not file_path.parent.exists():
|
||||||
|
file_path.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
# 写入文件
|
||||||
|
file_path.write_bytes(res.content)
|
||||||
|
logger.info("资源包更新完成,开始重启服务...")
|
||||||
|
SystemHelper.restart()
|
||||||
|
else:
|
||||||
|
logger.info("所有资源已最新,无需更新")
|
||||||
except json.JSONDecodeError:
|
except json.JSONDecodeError:
|
||||||
logger.error("资源包仓库数据解析失败!")
|
logger.error("资源包仓库数据解析失败!")
|
||||||
return
|
return None
|
||||||
else:
|
else:
|
||||||
logger.warn("无法连接资源包仓库!")
|
logger.warn("无法连接资源包仓库!")
|
||||||
return
|
return None
|
||||||
online_version = resource_info.get("version")
|
|
||||||
if online_version:
|
|
||||||
logger.info(f"最新资源包版本:v{online_version}")
|
|
||||||
# 需要更新的资源包
|
|
||||||
need_updates = {}
|
|
||||||
# 资源明细
|
|
||||||
resources: dict = resource_info.get("resources") or {}
|
|
||||||
for rname, resource in resources.items():
|
|
||||||
rtype = resource.get("type")
|
|
||||||
platform = resource.get("platform")
|
|
||||||
target = resource.get("target")
|
|
||||||
version = resource.get("version")
|
|
||||||
# 判断平台
|
|
||||||
if platform and platform != SystemUtils.platform():
|
|
||||||
continue
|
|
||||||
# 判断版本号
|
|
||||||
if rtype == "auth":
|
|
||||||
# 站点认证资源
|
|
||||||
local_version = self.siteshelper.auth_version
|
|
||||||
elif rtype == "sites":
|
|
||||||
# 站点索引资源
|
|
||||||
local_version = self.siteshelper.indexer_version
|
|
||||||
else:
|
|
||||||
continue
|
|
||||||
if StringUtils.compare_version(version, ">", local_version):
|
|
||||||
logger.info(f"{rname} 资源包有更新,最新版本:v{version}")
|
|
||||||
else:
|
|
||||||
continue
|
|
||||||
# 需要安装
|
|
||||||
need_updates[rname] = target
|
|
||||||
if need_updates:
|
|
||||||
# 下载文件信息列表
|
|
||||||
r = RequestUtils(proxies=settings.PROXY, headers=settings.GITHUB_HEADERS,
|
|
||||||
timeout=30).get_res(self._files_api)
|
|
||||||
if r and not r.ok:
|
|
||||||
return None, f"连接仓库失败:{r.status_code} - {r.reason}"
|
|
||||||
elif not r:
|
|
||||||
return None, "连接仓库失败"
|
|
||||||
files_info = r.json()
|
|
||||||
for item in files_info:
|
|
||||||
save_path = need_updates.get(item.get("name"))
|
|
||||||
if not save_path:
|
|
||||||
continue
|
|
||||||
if item.get("download_url"):
|
|
||||||
logger.info(f"开始更新资源文件:{item.get('name')} ...")
|
|
||||||
download_url = f"{settings.GITHUB_PROXY}{item.get('download_url')}"
|
|
||||||
# 下载资源文件
|
|
||||||
res = RequestUtils(proxies=self.proxies, headers=settings.GITHUB_HEADERS,
|
|
||||||
timeout=180).get_res(download_url)
|
|
||||||
if not res:
|
|
||||||
logger.error(f"文件 {item.get('name')} 下载失败!")
|
|
||||||
elif res.status_code != 200:
|
|
||||||
logger.error(f"下载文件 {item.get('name')} 失败:{res.status_code} - {res.reason}")
|
|
||||||
# 创建插件文件夹
|
|
||||||
file_path = self._base_dir / save_path / item.get("name")
|
|
||||||
if not file_path.parent.exists():
|
|
||||||
file_path.parent.mkdir(parents=True, exist_ok=True)
|
|
||||||
# 写入文件
|
|
||||||
file_path.write_bytes(res.content)
|
|
||||||
logger.info("资源包更新完成,开始重启服务...")
|
|
||||||
SystemUtils.restart()
|
|
||||||
else:
|
|
||||||
logger.info("所有资源已最新,无需更新")
|
|
||||||
|
|||||||
@@ -0,0 +1,51 @@
|
|||||||
|
from pathlib import Path
|
||||||
|
from typing import Tuple
|
||||||
|
|
||||||
|
import docker
|
||||||
|
|
||||||
|
from app.core.config import settings
|
||||||
|
from app.utils.system import SystemUtils
|
||||||
|
|
||||||
|
|
||||||
|
class SystemHelper:
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def can_restart() -> bool:
|
||||||
|
"""
|
||||||
|
判断是否可以内部重启
|
||||||
|
"""
|
||||||
|
return Path("/var/run/docker.sock").exists()
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def restart() -> Tuple[bool, str]:
|
||||||
|
"""
|
||||||
|
执行Docker重启操作
|
||||||
|
"""
|
||||||
|
if not SystemUtils.is_docker():
|
||||||
|
return False, "非Docker环境,无法重启!"
|
||||||
|
try:
|
||||||
|
# 创建 Docker 客户端
|
||||||
|
client = docker.DockerClient(base_url=settings.DOCKER_CLIENT_API)
|
||||||
|
# 获取当前容器的 ID
|
||||||
|
container_id = None
|
||||||
|
with open('/proc/self/mountinfo', 'r') as f:
|
||||||
|
data = f.read()
|
||||||
|
index_resolv_conf = data.find("resolv.conf")
|
||||||
|
if index_resolv_conf != -1:
|
||||||
|
index_second_slash = data.rfind("/", 0, index_resolv_conf)
|
||||||
|
index_first_slash = data.rfind("/", 0, index_second_slash) + 1
|
||||||
|
container_id = data[index_first_slash:index_second_slash]
|
||||||
|
if len(container_id) < 20:
|
||||||
|
index_resolv_conf = data.find("/sys/fs/cgroup/devices")
|
||||||
|
if index_resolv_conf != -1:
|
||||||
|
index_second_slash = data.rfind(" ", 0, index_resolv_conf)
|
||||||
|
index_first_slash = data.rfind("/", 0, index_second_slash) + 1
|
||||||
|
container_id = data[index_first_slash:index_second_slash]
|
||||||
|
if not container_id:
|
||||||
|
return False, "获取容器ID失败!"
|
||||||
|
# 重启当前容器
|
||||||
|
client.containers.get(container_id.strip()).restart()
|
||||||
|
return True, ""
|
||||||
|
except Exception as err:
|
||||||
|
print(str(err))
|
||||||
|
return False, f"重启时发生错误:{str(err)}"
|
||||||
@@ -11,7 +11,6 @@ from glob import glob
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import List, Optional, Tuple, Union
|
from typing import List, Optional, Tuple, Union
|
||||||
|
|
||||||
import docker
|
|
||||||
import psutil
|
import psutil
|
||||||
|
|
||||||
from app import schemas
|
from app import schemas
|
||||||
@@ -439,47 +438,6 @@ class SystemUtils:
|
|||||||
"""
|
"""
|
||||||
return [psutil.virtual_memory().used, int(psutil.virtual_memory().percent)]
|
return [psutil.virtual_memory().used, int(psutil.virtual_memory().percent)]
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def can_restart() -> bool:
|
|
||||||
"""
|
|
||||||
判断是否可以内部重启
|
|
||||||
"""
|
|
||||||
return Path("/var/run/docker.sock").exists()
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def restart() -> Tuple[bool, str]:
|
|
||||||
"""
|
|
||||||
执行Docker重启操作
|
|
||||||
"""
|
|
||||||
if not SystemUtils.is_docker():
|
|
||||||
return False, "非Docker环境,无法重启!"
|
|
||||||
try:
|
|
||||||
# 创建 Docker 客户端
|
|
||||||
client = docker.DockerClient(base_url='tcp://127.0.0.1:38379')
|
|
||||||
# 获取当前容器的 ID
|
|
||||||
container_id = None
|
|
||||||
with open('/proc/self/mountinfo', 'r') as f:
|
|
||||||
data = f.read()
|
|
||||||
index_resolv_conf = data.find("resolv.conf")
|
|
||||||
if index_resolv_conf != -1:
|
|
||||||
index_second_slash = data.rfind("/", 0, index_resolv_conf)
|
|
||||||
index_first_slash = data.rfind("/", 0, index_second_slash) + 1
|
|
||||||
container_id = data[index_first_slash:index_second_slash]
|
|
||||||
if len(container_id) < 20:
|
|
||||||
index_resolv_conf = data.find("/sys/fs/cgroup/devices")
|
|
||||||
if index_resolv_conf != -1:
|
|
||||||
index_second_slash = data.rfind(" ", 0, index_resolv_conf)
|
|
||||||
index_first_slash = data.rfind("/", 0, index_second_slash) + 1
|
|
||||||
container_id = data[index_first_slash:index_second_slash]
|
|
||||||
if not container_id:
|
|
||||||
return False, "获取容器ID失败!"
|
|
||||||
# 重启当前容器
|
|
||||||
client.containers.get(container_id.strip()).restart()
|
|
||||||
return True, ""
|
|
||||||
except Exception as err:
|
|
||||||
print(str(err))
|
|
||||||
return False, f"重启时发生错误:{str(err)}"
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def is_hardlink(src: Path, dest: Path) -> bool:
|
def is_hardlink(src: Path, dest: Path) -> bool:
|
||||||
"""
|
"""
|
||||||
|
|||||||
Reference in New Issue
Block a user