This commit is contained in:
2025-10-22 11:07:27 +08:00
parent 4333398dbe
commit daab333a49
7 changed files with 106 additions and 0 deletions

View File

@@ -0,0 +1,84 @@
import os, grp, shutil, subprocess, configparser
from pathlib import Path
from jupyterhub.spawner import Spawner
# host端的仓库目录
SHARED_ROOT = Path("/home/zhangyi/jupyter-collection")
# jyputerhub用户home目录
USER_HOME = Path("/home/jupyter-{username}")
# 分组信息路径
CTRL_FILE = SHARED_ROOT / ".hub" / "resource_map.ini"
# ========== 2. 读控制表 ==========
def load_ctrl():
"""返回 组->资源 和 组->用户 两个字典"""
cfg = configparser.ConfigParser()
cfg.read(CTRL_FILE)
res_map = {g: [r.strip() for r in v.split(",")]
for g, v in cfg.items("map")}
usr_map = {g: [u.strip() for u in v.split(",")]
for g, v in cfg.items("users")}
return res_map, usr_map
# ========== 3. post_auth_hook自动建用户+加组 ==========
def ensure_user_and_groups(authenticator, handler, authentication):
username = authentication['name']
res_map, usr_map = load_ctrl()
# 该用户应属的组
wanted_groups = [g for g, users in usr_map.items() if username in users]
if not wanted_groups: # 控制文件里没写就什么都不做
return authentication
# 确保组存在
for g in wanted_groups:
subprocess.run(["groupadd", "-f", g], check=False)
# 若系统账号不存在则创建Hub 自己会创 home这里确保 shell 账号)
#if subprocess.run(["id", "-u", username], capture_output=True).returncode != 0:
# subprocess.run([
# "useradd", "-m", "-s", "/bin/bash",
# "-d", str(USER_HOME).format(username=username), username
# ], check=False)
# 加组(幂等)
for g in wanted_groups:
subprocess.run(["usermod", "-aG", g, username], check=False)
return authentication
c.Authenticator.post_auth_hook = ensure_user_and_groups
# ========== 4. pre_spawn_hook重建干净 home + 只读挂 Git 资源 ==========
def prepare_user(spawner: Spawner):
username = spawner.user.name
user_dir = Path(str(USER_HOME).format(username=username))
# 1. 重建空 home保证无残留
if user_dir.exists():
shutil.rmtree(user_dir)
user_dir.mkdir(mode=0o700, parents=True, exist_ok=True)
# 2. 读控制表
res_map, _ = load_ctrl()
# 3. 取系统组
try:
gid_list = os.getgrouplist(username, grp.getpwnam(username).pw_gid)
except (KeyError, OSError):
return
user_groups = {grp.getgrgid(g).gr_name for g in gid_list}
# 4. 挂载该用户该看的资源(只读)
shared = user_dir / "shared"
shared.mkdir(exist_ok=True)
for grp_name in user_groups:
for res in res_map.get(grp_name, []):
res_path = SHARED_ROOT / res
if res_path.is_dir():
spawner.volumes[str(res_path)] = {
'bind': str(shared / res),
'mode': 'ro' # 重启即还原
}
c.Spawner.pre_spawn_hook = prepare_user

12
.hub/readme.md Normal file
View File

@@ -0,0 +1,12 @@
# jupyterhub相关配置说明
此文件夹包含了与jupyterhub有关的配置文件其中
1. **jupyter_config_backup.py** jupyterhub配置文件拷贝使用时将此文件拷贝至host端相应路径后重启hub即可。
```shell
sudo cp jupyter_config_backup.py /opt/tljh/config/jupyter_config.d/99-group-template.py
```
相关的配置说明见文件内注释。
2. **resource_map.ini** 对不同组别可获取资源与各组别内用户组成进行配置。

10
.hub/resource_map.ini Normal file
View File

@@ -0,0 +1,10 @@
# 第一个表定义了不同的组别可读取的资源路径名称
# <组名> = <路径名>, <路径名>
[map]
PrincipleOfGeophysics = geophysics_basic
GeophysicalInversion = geophysics_basic, geophysics_advanced
# 第二个表定义了每个组内的用户 用逗号区分
[users]
PrincipleOfGeophysics = student1, student2, student3
GeophysicalInversion = student4, student5