任务提交Lua插件
Job Submit Plugin是运行在头节点上的插件,在用户任务请求提交到头节点后、任务实际入队前运行。
作用
Job Submit Plugin可以对任务进行以下操作:
- 修改任务提交信息,例如修改任务的分区、核心以及内存数量
- 检查任务的信息,判断是否允许执行等
安装配置
在 slurm.conf 中添加:
JobSubmitPlugins=job_submit/lua
将Lua脚本保存到 /etc/slurm/job_submit.lua
支持的函数
-- 在任务提交时执行
function slurm_job_submit(job_desc, part_list, submit_uid)
end
-- 在修改任务的时候执行
function slurm_job_modify(job_desc, job_rec, part_list, modify_uid)
end
参数:
job_desc: 任务描述信息part_list: 所有分区信息submit_uid: 提交用户的UIDjob_rec: 当前任务记录(仅job_modify)modify_uid: 修改操作的用户UID(仅job_modify)
数据结构
Job Descriptor (job_desc)
| 字段名称 | 类型 | 描述 |
|---|---|---|
| account | string | 作业的账户名称 |
| admin_comment | string | 管理员评论 |
| array_task_cnt | number | 数组任务的数量 |
| batch_features | string | 作业的批处理特性 |
| burst_buffer | string | 作业的突发缓冲区 |
| comment | string | 作业的评论 |
| cpus_per_tres | string | 每个 TRES (资源 管理器) 的 CPU 数量 |
| delay_boot | number | 延迟启动时间 |
| direct_set_prio | number | 直接设置的优先级 |
| features | string | 作业的特性 |
| gres | string | 资源请求的 GRES (可扩展资源) |
| group_id | number | 作业的组 ID |
| job_id | number | 作业的 ID |
| job_state | number | 作业的状态 |
| licenses | string | 作业的许可证 |
| max_cpus | number | 作业可用的最大 CPU 数量 |
| max_nodes | number | 作业可用的最大节点数 |
| mem_per_tres | string | 每个 TRES 分配的内存 |
| min_cpus | number | 作业请求的最小 CPU 数量 |
| min_mem_per_node | number | 每个节点的最小内存需求 |
| min_mem_per_cpu | number | 每个 CPU 的最小内存需求 |
| min_nodes | number | 作业请求的最小节点数 |
| name | string | 作业名称 |
| nice | number | 作业的优先级偏移量 (调度优先级) |
| pack_job_id | number | 打包作业 ID |
| pack_job_id_set | string | 打包作业 ID 设置 |
| pack_job_offset | number | 打包作业偏移量 |
| partition | string | 作业所属的分区,注意为请求值,可能为空 |
| pn_min_cpus | number | 每个节点的最小 CPU 数量 |
| pn_min_memory | number | 每个节点的最小内存 (64 位整数) |
| priority | number | 作业的优先级 |
| qos | string | 作业的质量服务 (QoS) |
| reboot | number | 作业的重启设置 |
| req_switch | number | 作业请求的交换机信息 |
| site_factor | number | 站点因子,通常用于调度策略 |
| spank_job_env | table | SPANK (Slurm插件) 作业环境变量 |
| spank_job_env_size | number | SPANK 作业环境变量的大小 |
| time_limit | number | 作业的时间限制 |
| time_min | number | 作业的最短时间限制 |
| tres_bind | string | TRES 绑定信息 |
| tres_freq | string | TRES 频率信息 |
| tres_per_job | string | 每个作业的 TRES 数量 |
| tres_per_node | string | 每个节点的 TRES 数量 |
| tres_per_socket | string | 每个插槽的 TRES 数量 |
| tres_per_task | string | 每个任务的 TRES 数量 |
| user_id | number | 用户 ID |
| user_name | string | 用户名称 |
| wait4switch | number | 作业等待交换机的状态 |
| wckey | string | 作业的工作流键值 (workload key) |
Partition (part_list)
| 字段名称 | 类型 | 描述 |
|---|---|---|
| allow_accounts | string | 允许的账户名称 |
| allow_alloc_nodes | string | 允许分配的节点名称 |
| allow_groups | string | 允许的用户组名称 |
| allow_qos | string | 允许的 QoS 设置 |
| alternate | string | 替代的分区名称 |
| billing_weights_str | string | 分区的账单权重字符串 |
| default_time | number | 默认时间限制 (分钟) |
| def_mem_per_cpu | number | 每个 CPU 的默认内存需求 (如果是按 CPU 分配) |
| def_mem_per_node | number | 每个节点的默认内存需求 |
| deny_accounts | string | 拒绝的账户名称 |
| deny_qos | string | 拒绝的 QoS 设置 |
| flag_default | number | 是否为默认分区 (0: 否, 1: 是) |
| flags | number | 分区的标志字段 (例如是否启用等) |
| max_cpus_per_node | number | 每个节点允许的最大 CPU 数量 |
| max_mem_per_cpu | number | 每个 CPU 的最大内存需求 |
| max_mem_per_node | number | 每个节点的最大内存需求 |
| max_nodes | number | 最大节点数 |
| max_nodes_orig | number | 原始最大节点数 |
| max_share | number | 最大共享比例 |
| max_time | number | 最大时间限制 (分钟) |
| min_nodes | number | 最小节点数 |
| min_nodes_orig | number | 原始最小节点数 |
| name | string | 分区名称 |
| nodes | string | 节点列表 |
| priority_job_factor | number | 作业优先级因子 |
| priority_tier | number | 优先级等级 |
| qos | string | QoS 设置 |
| state_up | number | 分区是否处于活动状态 (0: 不活跃, 1: 活跃) |
全局对象 slurm
日志函数
| 字段/函数名 | 描述 |
|---|---|
| log_error | 记录错误日志 |
| log_info | 记录信息日志(级别0) |
| log_verbose | 记录详细日志(级别1) |
| log_debug | 记录调试日志(级别2) |
| log_debug2 | 记录更详细的调试日志(级别3) |
| log_debug3 | 记录更详细的调试日志(级别4) |
| log_debug4 | 记录最详细的调试日志(级别5) |
| log_user | 记录用户消息 |
错误代码
| 字段/函数名 | 描述 |
|---|---|
| ERROR | 表示一般错误 |
| FAILURE | 表示操作失败 |
| SUCCESS | 表示操作成功 |
| ESLURM_ACCESS_DENIED | 访问被拒绝 |
| ESLURM_ACCOUNTING_POLICY | 会计策略错误 |
| ESLURM_INVALID_ACCOUNT | 无效的账户 |
| ESLURM_INVALID_LICENSES | 无效的许可证 |
| ESLURM_INVALID_NODE_COUNT | 无效的节点计数 |
| ESLURM_INVALID_TIME_LIMIT | 无效的时间限制 |
| ESLURM_JOB_MISSING_SIZE_SPECIFICATION | 作业缺少大小规格 |
| ESLURM_MISSING_TIME_LIMIT | 缺少时间限制 |
其他定义
| 字段/函数名 | 描述 |
|---|---|
| ALLOC_SID_ADMIN_HOLD | 管理员保留的分配ID |
| ALLOC_SID_USER_HOLD | 用户保留的分配ID |
| INFINITE | 无限值 |
| INFINITE64 | 64位无限值 |
| MAIL_JOB_BEGIN | 作业开始时发送邮件 |
| MAIL_JOB_END | 作业结束时发送邮件 |
| MAIL_JOB_FAIL | 作业失败时发送邮件 |
| MAIL_JOB_REQUEUE | 作业重新排队时发送邮件 |
| MAIL_JOB_TIME100 | 作业时间达到100%时发送邮件 |
| MAIL_JOB_TIME90 | 作业时间达到90%时发送邮件 |
| MAIL_JOB_TIME80 | 作业时间达到80%时发送邮件 |
| MAIL_JOB_TIME50 | 作业时间达到50%时发送邮件 |
| MAIL_JOB_STAGE_OUT | 作业阶段结束时发送邮件 |
| MEM_PER_CPU | 每个CPU的内存 |
| NICE_OFFSET | 优先级偏移量 |
| JOB_SHARED_NONE | 作业不共享 |
| JOB_SHARED_OK | 作业共享 |
| JOB_SHARED_USER | 用户共享作业 |
| JOB_SHARED_MCS | MCS共享作业 |
| NO_VAL64 | 64位无效值 |
| NO_VAL | 无效值 |
| NO_VAL16 | 16位无效值 |
| NO_VAL8 | 8位无效值 |
| SHARED_FORCE | 强制共享 |
作业描述位标志
| 字段/函数名 | 描述 |
|---|---|
| GRES_DISABLE_BIND | 禁用资源绑定 |
| GRES_ENFORCE_BIND | 强制资源绑定 |
| KILL_INV_DEP | 杀死无效依赖 |
| NO_KILL_INV_DEP | 不杀死无效依赖 |
| SPREAD_JOB | 分散作业 |
| USE_MIN_NODES | 使用最小节点数 |
全局函数
| 字段/函数名 | 描述 |
|---|---|
| log | 通用log函数: log(level, msg) |
| error | 错误日志: error(msg) |
| time_str2mins | slurm格式的时间格式,输出分钟 |
使用示例
示例1: 限制部分用户使用部分分区
-- list of UIDs to reistrict from submmitting
local uids_to_restrict = {
2000,
2001,
}
-- partitions to restrict user to submit to
local partitions_to_restrict = {
"Compute",
}
local function get_default_partition(part_list)
for name, part in pairs(part_list) do
if part.flag_default == 1 then
return name
end
end
return nil
end
-- slurm_job_submit: process the submitted job requests
function slurm_job_submit(job_desc, part_list, submit_uid)
-- if submit_uid is in the list of uids to restrict, then check if the job is targeting the restricted partition
if submit_uid == 0 then
return slurm.SUCCESS
end
local to_check = false
for _, uid in ipairs(uids_to_restrict) do
if submit_uid == uid then
slurm.log_info("User " .. submit_uid .. " is in the list of uids to restrict")
to_check = true
break
end
end
if not to_check then
return slurm.SUCCESS
end
-- check if the job is targeting the restricted partition
local partition = job_desc.partition
if not partition then
-- this is for default partition
partition = get_default_partition(part_list)
end
if not partition then
slurm.log_error("Partition not found")
return slurm.ERROR
end
for _, part in ipairs(partitions_to_restrict) do
if partition == part then
slurm.log_info("User " .. submit_uid .. " is not allowed to submit jobs to partition " .. partition)
return slurm.ESLURM_ACCESS_DENIED
end
end
return slurm.SUCCESS
end
-- slurm_job_modify: called when a job is modified
function slurm_job_modify(job_desc, job_rec, part_list, modify_uid)
return slurm.SUCCESS
end