mirror of
https://github.com/jumpserver/jumpserver.git
synced 2026-07-15 15:29:33 +00:00
perf: locate replay in terminal's configured storage first when playing
This commit is contained in:
@@ -10,7 +10,7 @@ from terminal.models import ReplayStorage
|
||||
logger = get_logger(__name__)
|
||||
|
||||
|
||||
def get_multi_object_storage():
|
||||
def get_multi_object_storage(name=None):
|
||||
replay_storages = ReplayStorage.objects.all()
|
||||
configs = {}
|
||||
for storage in replay_storages:
|
||||
@@ -21,6 +21,9 @@ def get_multi_object_storage():
|
||||
configs[storage.name] = storage.config
|
||||
if settings.SERVER_REPLAY_STORAGE:
|
||||
configs['SERVER_REPLAY_STORAGE'] = settings.SERVER_REPLAY_STORAGE
|
||||
# 指定存储名时仅构造该存储, 用于优先直连文件所在的存储, 避免遍历探测
|
||||
if name is not None:
|
||||
configs = {name: configs[name]} if name in configs else {}
|
||||
if not configs:
|
||||
return None
|
||||
storage = jms_storage.get_multi_object_storage(configs)
|
||||
@@ -40,31 +43,42 @@ class BaseStorageHandler(object):
|
||||
def find_local(self):
|
||||
raise NotImplementedError
|
||||
|
||||
def get_preferred_storage_name(self):
|
||||
# 文件优先查找的存储名, 返回 None 表示直接遍历所有存储
|
||||
return None
|
||||
|
||||
def download(self):
|
||||
storage = get_multi_object_storage()
|
||||
if not storage:
|
||||
# 优先只查文件所属的存储, 未指定或未命中时回退遍历所有存储
|
||||
preferred = self.get_preferred_storage_name()
|
||||
storage_names = [preferred, None] if preferred else [None]
|
||||
msg, found_storage = '', False
|
||||
for name in storage_names:
|
||||
storage = get_multi_object_storage(name)
|
||||
if not storage:
|
||||
continue
|
||||
found_storage = True
|
||||
|
||||
remote_path, local_path = self.get_file_path(storage=storage)
|
||||
if not remote_path:
|
||||
msg = f'Not found {self.NAME} file'
|
||||
continue
|
||||
|
||||
# 保存到storage的路径
|
||||
target_path = os.path.join(default_storage.base_location, local_path)
|
||||
target_dir = os.path.dirname(target_path)
|
||||
if not os.path.isdir(target_dir):
|
||||
make_dirs(target_dir, exist_ok=True)
|
||||
|
||||
ok, err = storage.download(remote_path, target_path)
|
||||
if ok:
|
||||
url = default_storage.url(local_path)
|
||||
return local_path, url
|
||||
msg = f'Failed download {self.NAME} file: {err}'
|
||||
if not found_storage:
|
||||
msg = f"Not found {self.NAME} file, and not remote storage set"
|
||||
return None, msg
|
||||
|
||||
remote_path, local_path = self.get_file_path(storage=storage)
|
||||
if not remote_path:
|
||||
msg = f'Not found {self.NAME} file'
|
||||
logger.error(msg)
|
||||
return None, msg
|
||||
|
||||
# 保存到storage的路径
|
||||
target_path = os.path.join(default_storage.base_location, local_path)
|
||||
target_dir = os.path.dirname(target_path)
|
||||
if not os.path.isdir(target_dir):
|
||||
make_dirs(target_dir, exist_ok=True)
|
||||
|
||||
ok, err = storage.download(remote_path, target_path)
|
||||
if not ok:
|
||||
msg = f'Failed download {self.NAME} file: {err}'
|
||||
logger.error(msg)
|
||||
return None, msg
|
||||
url = default_storage.url(local_path)
|
||||
return local_path, url
|
||||
logger.error(msg)
|
||||
return None, msg
|
||||
|
||||
def get_file_path_url(self):
|
||||
local_path, url = self.find_local()
|
||||
|
||||
@@ -14,9 +14,24 @@ from .base import BaseStorageHandler, get_multi_object_storage
|
||||
logger = get_logger(__name__)
|
||||
|
||||
|
||||
def get_session_preferred_storage_name(session):
|
||||
"""
|
||||
会话所属终端(组件)配置的录像存储名, 录像大概率上传在该存储上, 优先在其中查找
|
||||
terminal 可能已被删除 (on_delete=DO_NOTHING), 取不到时返回 None 表示无优先存储
|
||||
"""
|
||||
try:
|
||||
terminal = session.terminal
|
||||
except Exception:
|
||||
return None
|
||||
return terminal.replay_storage if terminal else None
|
||||
|
||||
|
||||
class ReplayStorageHandler(BaseStorageHandler):
|
||||
NAME = 'REPLAY'
|
||||
|
||||
def get_preferred_storage_name(self):
|
||||
return get_session_preferred_storage_name(self.obj)
|
||||
|
||||
def get_file_path(self, **kwargs):
|
||||
storage = kwargs['storage']
|
||||
# 获取外部存储路径名
|
||||
@@ -55,10 +70,6 @@ class SessionPartReplayStorageHandler(object):
|
||||
return None, '{} not found.'.format(part_filename)
|
||||
|
||||
def download_part_file(self, part_filename):
|
||||
storage = get_multi_object_storage()
|
||||
if not storage:
|
||||
msg = "Not found {} file, and not remote storage set".format(part_filename)
|
||||
return None, msg
|
||||
local_path = self.obj.get_replay_part_file_local_storage_path(part_filename)
|
||||
remote_path = self.obj.get_replay_part_file_relative_path(part_filename)
|
||||
|
||||
@@ -69,7 +80,21 @@ class SessionPartReplayStorageHandler(object):
|
||||
if not os.path.isdir(target_dir):
|
||||
make_dirs(target_dir, exist_ok=True)
|
||||
|
||||
ok, err = storage.download(remote_path, target_tmp_path)
|
||||
# 优先只查所属终端配置的存储, 未配置或未命中时回退遍历所有存储
|
||||
preferred = get_session_preferred_storage_name(self.obj)
|
||||
storage_names = [preferred, None] if preferred else [None]
|
||||
ok, err, found_storage = False, None, False
|
||||
for name in storage_names:
|
||||
storage = get_multi_object_storage(name)
|
||||
if not storage:
|
||||
continue
|
||||
found_storage = True
|
||||
ok, err = storage.download(remote_path, target_tmp_path)
|
||||
if ok:
|
||||
break
|
||||
if not found_storage:
|
||||
msg = "Not found {} file, and not remote storage set".format(part_filename)
|
||||
return None, msg
|
||||
if not ok:
|
||||
msg = 'Failed download {} file: {}'.format(part_filename, err)
|
||||
logger.error(msg)
|
||||
|
||||
Reference in New Issue
Block a user