跳转至

SOP:Cadence IC25.10 (Virtuoso Studio) 安装到 NFS 共享存储

工程:ic25_install_20260924(相对项目根 Cadence/)。 实现体:main.py / deployer.py / utils/;本文第 5 章代码块为文档呈现,以实现体为准。 单次变更档案;本文累积追加,交接现状看 docs/HANDOFF.md。

目录

  1. 背景 / 2. 目标 / 3. 前置条件 / 4. 影响范围 / 5. 分步操作 / 6. 验证 / 7. 回滚 / 8. 风险说明 / 附录

1. 背景

EDA 行业存储方案要求工具装 NFS 共享(Tier1 /data/nfs/tools → 客户端 /tools 只读挂载), Slurm(.18/.19/.20)与 LSF 集群经 module 共享使用。2026-09-24 用户确认: 安装到 /data/nfs/tools/cadence/virtuoso/IC25.10.000(三级版本化),license 后补, modulefile 生成属 slurm_ins 工程、本次不做。

2. 目标(可验证状态)

  • [x] 三计算节点 test -d /tools/cadence/virtuoso/IC25.10.000 且 find … -name virtuoso 命中
  • [x] 目标 root:root,目录 755/文件 644,无 group/other 写位;客户端 test -w 失败
  • [x] 介质 5 卷 sha256 全过(来源锁定,无跳过开关)
  • [x] 幂等:复跑 install → skipped 零变更;drift RC=0
  • [ ] 遗留:modulefile 生成、license、客户端系统库补齐(见第 8 章与 HANDOFF)

3. 前置条件(已全部落为实现体 precheck 检查项)

条件 检查项 通过标准
介质完整 media_sha256 5 卷 sha256 与配置一致(BLOCK 否则)
目标盘空间 target_disk /data/nfs/tools 可用 ≥ 10GB(BLOCK)
解压盘空间 image_disk 工程根可用 ≥ 25GB(BLOCK)
执行身份 sudo sudo -n true 可用(BLOCK)
无在跑作业 三节点 scheduler squeue -h -w <node> 空(BLOCK)
节点基线 os / ntp / root Rocky 9、时钟 ≤5s、root 免密
目标干净 install_dir 不存在或已安装;半装即 BLOCK(先 rollback)
license license_connectivity 本环境经 skip_checks 豁免(WARN 登记,不静默)
Lustre lustre 只读确认挂载(不影响本安装;不动 fstab)

4. 影响范围

  • 变更主机:仅宿主 dell-R620(192.168.31.249,安装器执行端)。
  • 共享影响:新增 /data/nfs/tools/cadence/virtuoso/IC25.10.000(33G)与 /opt/iscape; 三计算节点经只读挂载被动可见,不改任何客户端配置。
  • 是否停服:否;无需停 Slurm/LSF。窗口要求:squeue 空(precheck 强制)。
  • 在跑作业:执行前实测三节点均无作业。

5. 分步操作

本章回答"这次到底在机器上做了什么、为什么这么做",只看本章即可理解安装全流程。

实现体附注:编排入口 main.py(precheck / install [--dry-run] / patch / deps / cleanup / rollback / drift,实现体 deployer.py + utils/ic_install.py);幂等、失败 2 次即停、状态门禁由实现体保证。以下每步给出等价 shell——实现体在机器上真实执行的动作,供理解流程与手工复现;执行以实现体为准。沙箱环境下变更入口须走"批准 + setsid"通道(见第 8 章)。

步骤 1:只读预检查(门禁,零变更)

全链路只读探测,任一 BLOCK 即拒绝进入安装:介质 5 卷 sha256 全量比对、目标目录状态、磁盘余量、sudo -n 免密、Lustre 挂载、调度器空、6 台客户端依赖 rpm。

坑:① 半装目录(存在但不完整)直接 BLOCK——带病安装会留下更脏的现场,必须先 rollback --force 清理再重跑(本次实测生效);② sha256 不符按介质损坏 BLOCK,无跳过开关;③ 依赖缺失的修复入口是 deps 子命令,不是绕过门禁。

cd <项目根>/ic25_install_20260924
sha256sum ../IC25.10.000/Base_IC25.10.000_lnx86_*of5.tar   # 逐一比对 config 中锁定的 sha 值
df -B1G --output=avail /data/nfs/tools                      # 预期 ≥10G(镜像另需 ≥25G)
sudo -n true && echo sudo-ok                                # 写 /opt 与安装目录必需免密 root
findmnt -n /mnt/lustre                                      # 介质所在 Lustre 必须已挂载
squeue                                                      # 调度器必须无在跑作业
ssh root@192.168.31.18 'rpm -q motif libXmu libXp libXt mesa-libGLU libX11-xcb'  # 6 台逐台,缺任一即 BLOCK

预期:EXIT=0,报告落 reports/precheck-*.md。失败判断:按报告 BLOCK 项修复——缺包跑 deps、半装跑 rollback --force、sha 不符更换介质——再重跑。

步骤 2:预演(dry-run,硬承诺零改动)

实现体在内存中推演并产出 reports/plan-*.yaml(动作/目标/前值/后值),无机器变更,故无独立等价 shell;入口见章首实现体附注。

坑:dry-run 时镜像尚未解压,InstallScape 步骤只输出计划不拦截——预演通过 ≠ 安装必然通过,真实执行会重新过门禁。预期:EXIT=0。

步骤 3:解压 5 卷介质为镜像

5 卷 tar 依次解到 scratch/IC25.10.000_lnx86.Base(tar 顶层即该目录名),得到 CDROM1 镜像。

坑:① tar 顶层目录名必须与 config image.dir 一致,解压后缺 CDROM1/SETUP.SH 即判失败;② 半解压保护——完成标记记录已解卷清单,中断后不会被误判完成;③ 单卷超时 1800s。

cd <项目根>/ic25_install_20260924
for v in 1 2 3 4 5; do
  tar -xf ../IC25.10.000/Base_IC25.10.000_lnx86_${v}of5.tar -C scratch/
done
test -f scratch/IC25.10.000_lnx86.Base/CDROM1/SETUP.SH      # 完整性判据,缺即失败
touch scratch/.image_extracted                              # 完成标记(手工等价;实现体维护卷清单)

预期:rc=0 且 marker 存在。失败判断:tar 报错多为卷序/路径错;修复后重跑,幂等承接。

步骤 4:InstallScape 就位

从镜像取 IS*.t.Z kit 解压到 /opt/iscape(install 层级之外,长期保留的官方安装器)。

坑:① .t.Z 是 compress(LZW) 格式,必须 zcat 管道给 tar,tar -z(按 gzip 解)会失败;② /opt 普通用户无写权限,目录须 sudo mkdir;③ 装在层级外——回滚删安装目录时不删它。

sudo mkdir -p /opt/iscape
zcat < scratch/IC25.10.000_lnx86.Base/CDROM1/IS*.t.Z | tar -xf - -C /opt/iscape
test -f /opt/iscape/iscape.05.01-p001/bin/iscape.sh         # 就位判据(版本目录以 config iscape_home 为准)

预期:iscape.sh 存在。失败判断:zcat/tar 报错查权限与 kit 路径;解压后无 iscape.sh 说明 kit 版本目录名与 config 不符。

步骤 5:InstallScape 批处理安装(核心)

把镜像装入安装目录。InstallScape 支持 -batch 非交互(参数来自 -help install 实测),无需桌面环境与图形点击;目标目录须 root 属主,先 sudo mkdir 预建。

坑:① 本步失败会留下「半装」中间态,直接重跑被步骤 1 门禁拦截——install 模式实现体自动 purge 半装后原参数重试一次,连续 2 次失败即停;patch 模式不 purge(依赖已装 Base,删了失去回滚依据),须人工 rollback;② 超时 7200s,长任务用 setsid 脱离会话(第 8 章);③ 运行日志逐次落盘 logs/iscape_run_*.log。

sudo mkdir -p /data/nfs/tools/cadence/virtuoso/IC25.10.000
sudo env -u DISPLAY /opt/iscape/iscape.05.01-p001/bin/iscape.sh -batch \
  majorAction=InstallFromArchive \
  archiveDirectory=scratch/IC25.10.000_lnx86.Base/CDROM1 \
  installDirectory=/data/nfs/tools/cadence/virtuoso/IC25.10.000

预期:rc=0,logs/iscape_run_*.log 无 ERROR,安装状态探测 DONE。失败判断:超时或探测「半装」→ 先读日志定位;不可自愈则按第 7 章回滚。

步骤 6:权限只读收敛(高危)

属主收敛 root:root、权限 u=rwX,go=rX——对外只读、保留执行位,防止用户误写共享工具树。

坑:① 判据只看常规文件/目录——symlink 由内核忽略、恒 777,曾误报 3683 个(第 8 章踩坑);② u=rwX 中大写 X 只给目录与已可执行文件加 x,不能硬套 755/644。

# 高危:属主与全局权限变更(回滚 = 重新执行本步反向不可逆,仅影响安装目录内属主/权限)
sudo chown -R root:root /data/nfs/tools/cadence/virtuoso/IC25.10.000
sudo chmod -R u=rwX,go=rX /data/nfs/tools/cadence/virtuoso/IC25.10.000
find /data/nfs/tools/cadence/virtuoso/IC25.10.000 \( -type f -o -type d \) -perm /022 | head   # 预期空

预期:复核命令输出空(无 group/other 写位)。失败判断:非空 → 重跑 chmod;仍失败查实现体 probe_perms 日志。

步骤 7:验证(本地 + 6 台客户端)

实现体 validate 自动执行:本地安装/只读状态 + 各客户端 /tools 视图可见、virtuoso 二进制存在、ldd 真缺=0、挂载只读。命令与判据见第 6 章(同一事实只写一处)。

坑:裸 ldd 的 not found 分两类——树内库(运行时靠 LD_LIBRARY_PATH 解析,正常)与真缺系统库;把树内库计入缺失会使验证恒失败,实现体已按"真缺"判据处理。

步骤 8:镜像回收(高危)

删除解压镜像与探测临时目录(可再生,恢复 = 重跑步骤 3);介质 tar 与安装目录不删。

坑:白名单推导——目标必须落在工程 scratch/ 内、具体路径非通配、系统盘(findmnt 实证)之外,推导失败拒绝执行;且须 --force 显式确认。

# 高危:删除解压镜像(可再生;恢复 = 重新解压 5 卷介质)
rm -rf -- scratch/IC25.10.000_lnx86.Base scratch/.image_extracted scratch/iscape_probe

预期:目标消失。失败判断:实现体拒绝删除 = 白名单推导未过,核对路径而非换参数硬删。

步骤 9:漂移/幂等复核

收尾复核七项状态全 done(drift,入口见章首附注),随后再跑 install 应 skipped 零变更——两次执行零差异即幂等证明。手工等价判据:

test -f scratch/.image_extracted && echo image-done
test -f /opt/iscape/iscape.05.01-p001/bin/iscape.sh && echo iscape-done
test -f /data/nfs/tools/cadence/virtuoso/IC25.10.000/tools.lnx86/dfII/bin/64bit/virtuoso && echo install-done
find /data/nfs/tools/cadence/virtuoso/IC25.10.000 \( -type f -o -type d \) -perm /022 | head -1  # 空=perms-done

预期:drift RC=0(七项全 done)、install 返回 skipped。失败判断:任一 pending → 对应步骤重跑(幂等承接);unknown → 排查探测环境,不得据此变更。

失败处置总则:同一逻辑连续失败 2 次实现体自动终止(不换参数);先读 logs/deploy.log 与 logs/iscape_run_*.log 定位,再按第 7 章回滚或修正重跑。

6. 验证

# 客户端三节点(逐台;预期 VIRTUOSO 路径 + RO)
for h in 192.168.31.18 .19 .20; do ssh root@$h '
  MP=/tools/cadence/virtuoso/IC25.10.000
  V=$(find "$MP" -type f -name virtuoso -path "*/bin/*" -print -quit)
  echo "$V"; ldd "$V" 2>&1 | grep -c "not found"
  test -w "$MP" && echo WRITABLE || echo RO'; done

# 本地收敛与漂移
.venv/bin/python main.py drift                          # 预期 RC=0
du -sh /data/nfs/tools/cadence/virtuoso/IC25.10.000    # 预期 ~33G

判定说明:裸 ldd 报 not found 分两类——树内已有(约 181,运行时靠 LD_LIBRARY_PATH 解析,属正常)与真缺系统库(约 38,遗留待办,见第 8 章); 对比时注意 symlink 不进 -type f 名单(踩坑记录见第 8 章)。

7. 回滚

  • 回退目标:删除安装目录 = rollback --force(安全推导:install_dir 必须等于 install_root/vendor/tool/version 四级拼接 + findmnt 实证非系统盘,推导失败拒绝执行)。
  • 镜像清理回退:cleanup --force 删的是可再生临时文件,恢复 = 重新解压介质。
  • 备份位置与台账:本工程为纯新增、无 .bak 前置备份;删除类动作逐条登记于 backup/README.md(含对象、时间、因何产生、回滚方式、何时可删)。
  • 回滚后验证:test -d <目标> 应失败;drift 中 install 项应转 pending。

8. 风险说明(含本次实测踩坑)

风险 实测情况 缓解
Trae 沙箱拦截工作目录外写 曾 2 次拦截 /opt/iscape;nohup 后台进程又被 harness 杀 变更命令走"批准(requires_approval)+ setsid nohup"通道;已验证可脱离
半装目录带病安装 失败重试的 purge 曾遗留空目录 precheck 识别半装即 BLOCK,强制先 rollback --force(本次实测生效)
权限复核判据 曾用 find -perm -u+w 与 755 目标自相矛盾;后误报 3683 个 symlink(恒 777、内核忽略) 判据最终为"仅常规文件/目录无 g/o 写位",probe_perms 单源
运行环境缺库 裸 ldd 报 219;真缺约 38 个系统包(X11/Motif/GL/fontconfig/freetype/leveldb/fmt,Rocky9 最小化) 属"运行就绪"后续:补包 + modulefile 设 LD_LIBRARY_PATH 后复验
license 未部署 无 FlexLM server(用户决策后补) 不验证 virtuoso 启动;module load 前必须先补 license
SELinux Enforcing 三节点实测 Enforcing(期望 permissive) 当前 NFS 读+执行未受影响;若后续启动被拒再评估 setenforce 0
基线差异 介质基线 RHEL 8.4,运行端 Rocky 9.8 非 Cadence 官方认证组合;已知风险,靠 ldd/启动实测定夺
失败 2 次即停 全程遵守(沙箱期 2 次、代码 bug 期各 2 次均自动终止) 不换参数绕过;修根因后重跑(幂等承接)

变更 2(2026-09-25):patch 子命令(Hotfix IC25.10.040 集成)

2.1 背景

介质目录新增 Hotfix IC25.10.040(Virtuoso Studio IC25.1 ISR4,4 卷 15G)。实测取证: Hotfix 仅含 338 个 kit 主名(Base 417),缺 Base 中未变化的 kit,不能脱离 Base 单独安装; share/version/<kit> 文件记录 kit 版本(如 dfIIbase.lnx86 当前 25.10/p038,Hotfix 为 s143), 是打补丁前后的真实系统标识。用户决策:集成 patch 子命令,回滚 = 删目录重装 Base 000。

2.2 目标(可验证状态)

  • [x] main.py patch 子命令可用(--dry-run EXIT=0,计划含解压 4 卷 + iscape Hotfix/CDROM1)
  • [x] patch --dry-run 零改动(scratch/安装目录 mtime/version md5 前后快照一致)
  • [x] drift 含 patch 维度:未打补丁 → patch pending、退出码 1
  • [x] 真实执行:probe_patch 12 kit 全匹配 → done(2026-09-25 21:11 实测,drift RC=0)
  • [x] 三节点验证:virtuoso 路径 + 权限 RO 通过;ldd 真缺=0 于 2026-09-25 22:40 闭合 (依赖经变更 3 deps 补齐、验证判据同步修正为"真缺"计数,见变更 3 §3.2/§3.6)
  • [x] 幂等:复跑 patch → 零变更 skipped;drift RC=0

2.3 前置条件(继承第 3 章全部检查项,另加)

条件 检查项 通过标准
Base 已装 模块 pre_check probe_install=done,否则拒绝 patch
补丁介质 patch.media sha256 4 卷全匹配(BLOCK,无跳过开关)
非半升级态 probe_patch detail 含"半升级"即 BLOCK,强制先 rollback
无在跑作业 三节点 scheduler squeue 空(BLOCK),覆盖第 3 章

2.4 影响范围

  • 变更主机:仅宿主(安装器执行端);共享影响 = 原地覆盖 /data/nfs/tools/cadence/virtuoso/IC25.10.000 (路径不变,仍叫 000;kit 版本升至 25.10.040)。
  • 三计算节点经只读挂载被动可见;打补丁期间客户端可见混合版本,窗口要求 squeue 空。
  • 是否停服:否;无需停 Slurm/LSF。

2.5 分步操作(以实现体为准)

cd <项目根>/ic25_install_20260924

# ① 预演(零改动承诺;含 4 卷补丁介质 sha256 + 三节点门禁)
.venv/bin/python main.py patch --dry-run               # 预期 EXIT=0,reports/plan-*.yaml 落盘

# ② 真实打补丁(沙箱环境走"批准 + setsid"通道,见第 8 章)
setsid nohup .venv/bin/python main.py patch > /tmp/patch_run.out 2>&1 < /dev/null &
# 内部步骤:补丁介质 sha 门禁 → 解压 4 卷(独立 marker)→ iscape 复用 /opt/iscape
#          → iscape.sh -batch InstallFromArchive archiveDirectory=<Hotfix>/CDROM1
#          → 权限只读收敛 → probe_patch + 三节点验证
# 注意:失败 2 次即终止且【不】自动删目录(patch 依赖已装 Base,purge 会失去回滚依据)

# ③ 镜像回收(高危;cleanup 现已一并覆盖 patch.image 的 dir/marker)
.venv/bin/python main.py cleanup --force               # 预期 success

# ④ 幂等/漂移复核
.venv/bin/python main.py drift                         # 预期 RC=0(含 patch 项全 done)
.venv/bin/python main.py patch                         # 预期 skipped 零变更

2.6 验证

# 期望态核心判据:12 个 kit 版本全匹配
for k in dfIIbase icfb64b abstract64b adexl64b analogLib64b CSRCO64b \
         cdaCore64b AnlsCommon64b MiscLicDaemon SftShrTools ExtCce64b SmartSearch; do
  printf "%-16s %s\n" "$k" "$(tr '\n' '/' < /data/nfs/tools/cadence/virtuoso/IC25.10.000/share/version/$k.lnx86)"
done                                                   # 预期 s143/p001/s415/s044 与配置 expect 一致

.venv/bin/python main.py drift                          # 预期 RC=0,patch 项 done
# 三节点可见性沿用第 6 章命令(virtuoso 路径 + ldd + RO 不变)

实测记录(2026-09-25 真实执行,执行窗口 squeue 空)

时点 动作 结果
20:39 patch --dry-run 门禁 EXIT=0,plan-20260925-204106.yaml 落盘
20:43–20:49 sha256(4 卷全匹配)→ 解压 4 卷 marker .patch_image_extracted 落盘
20:49–21:10 iscape InstallFromArchive(Hotfix/CDROM1) Install from CDROM(s) Successful
21:10 权限收敛 root:root u=rwX,go=rX
21:11 probe_patch + 三节点验证 probe 12/12 kit 匹配;三节点路径+RO 过,ldd NOTFOUND=226 → 模块 failed
21:15 / 21:22 drift / 复跑 patch RC=0 全 done / RC=0 skipped 零变更
  • 模块耗时 1562.67s;ldd 失败为 HANDOFF 待办 #3 的既知客户端缺库(约 38 个),非补丁引入、非半升级态 (drift 判定 12/12 全匹配即证非半升级)。补验收随补库后一并做。
  • 证据:logs/deploy.log、reports/precheck-20260925-203938.md、reports/plan-20260925-204106.yaml、 reports/drift-20260925-211502.md;本次执行输出 /tmp/patch_run.out(临时,未留档)。

2.7 回滚

  • 补丁无反向补丁(Cadence 不提供):回滚 = rollback --force 删 install_dir 后用 Base 5 卷重装 000(约 19G,install 子命令幂等承接)。Base 介质因此必须长期保留。
  • 半升级态(iscape 中途失败残留部分新 kit)唯一处置也是 rollback 重装;工具侧已 BLOCK 禁止 在半升级态上继续 patch。
  • 备份与台账:本次代码改动前的 7 个文件备份于 backup/(backup/config/、backup/utils/、 backup/*.py,.bak.20260925-103218),登记见 backup/README.md; 回滚代码 = 用对应 .bak 覆盖还原。
  • 回滚后验证:test -d <安装目录> 失败;drift 中 install 项转 pending。

2.8 风险说明

风险 说明 缓解
覆盖不可逆 patch 原地覆盖 kit,无反向补丁 回滚=删目录重装 Base;Base 5 卷永久保留
半升级中间态 iscape 中途失败 → 000+040 混合 probe_patch 部分匹配判"半升级"→ BLOCK 强制 rollback;patch 失败不 purge 目录
客户端可见混合版本 打补丁期间 /tools 视图处于过渡态 窗口 squeue 空(precheck 强制);打完即收敛
期望集抽样 probe 期望 12 kit(共 143 个会变) 覆盖各版本线;全量比对见变更 2 取证记录(本节附录)
dry-run 镜像前置检查 _step_run_iscape 曾在 dry-run 因镜像未解压误报失败 已修:镜像完整性检查仅真实执行时生效(实测 EXIT=0)
文件 用途
main.py / deployer.py / utils/ 实现体(precheck/install/patch/cleanup/rollback/drift)
config/ic25_install.yaml(样例 .example) 配置真源:介质 sha256(含 patch 段)、路径、阈值、豁免
backup/config|utils/*.bak.20260925-103218 等 7 件 变更 2 前的代码/配置备份(回滚代码用)
reports/precheck-*.md / plan-*.yaml / drift-*.md 门禁、计划、漂移报告
reports/install_report.md 安装记录与实测数据
logs/deploy.log / logs/iscape_run_*.log 运行与安装器日志
backup/README.md 删除类动作台账
docs/HANDOFF.md 交接快照(现状与待办)

变更 3(2026-09-25):deps 子命令(客户端系统依赖声明式管理)

3.1 背景

patch 真实执行的三节点验证暴露客户端系统库缺失:裸 ldd NOTFOUND=226, 与安装树差集后真缺 6 个(Motif/X11 扩展家族 + GLU;其余 217 个为树内库, 运行时由环境脚本/modulefile 的 LD_LIBRARY_PATH 解析)。手工 dnf 补包不可复用; 用户决策:依赖做成部署工具能力——配置声明、工具统一满足,新节点扩容加入 nodes 后跑 deps 即可。同时发现既有三节点验证判据缺陷(裸 ldd 计数把 树内库计为缺失 → 验证恒失败),一并修正为"真缺"判据。

3.2 目标(可验证状态)

  • [x] 配置段 client_deps(packages + ldd_anchor)入 yaml 与样例,校验齐备 (非空、无重复、包名格式、绝对路径)
  • [x] deps 子命令:三态探测(逐节点 rpm -q)→ 计划 → 逐台 dnf → rpm + ldd 双复验; --dry-run 零改动;不接全量 precheck 门禁(缺包 BLOCK 若挡住 deps 自身即自我死锁)
  • [x] precheck 新增 client_deps 检查项:缺包 BLOCK,提示先跑 deps
  • [x] drift 新增 client_deps 维度(与 precheck/deps 共用同一探测函数)
  • [x] 三节点真实补齐 6 包,ldd 真缺=0
  • [x] 幂等:复跑 deps 跳过、precheck RC=0、drift RC=0
  • [x] 验证判据修正:install/patch 三节点验证改按"真缺"计数,实测三节点 NOTFOUND=0 + RO

3.3 前置条件

条件 检查项 通过标准
配置声明 config_validate client_deps 段 packages 非空无重复、包名合法、ldd_anchor 绝对路径
节点可达 precheck 三节点 ssh root 免密可达(探测失败 unknown 即中止)
包源可用 节点 dnf 源 AppStream/BaseOS/EPEL(本集群实测在线源可用)
作业窗口 三节点 squeue 空。本次执行依据 21:39 precheck 实测 squeue 空,22:14 执行时未实时复核——后续执行前须复核

3.4 影响范围

  • 变更主机:三计算节点本地(/usr/lib64 + ld.so.cache);不碰 NFS 安装树与调度配置。
  • 是否停服:否;装运行时不重启任何服务。窗口要求见 3.3。
  • 扩容影响面:新节点只需"加入 nodes + SSH 可达 + dnf 源可用",跑 deps 即齐依赖。

3.5 分步操作(以实现体为准)

cd <项目根>/ic25_install_20260924   # 实现体:deployer.py cmd_deps + utils/ic_state.py probe_client_deps

# ① 预演(只读;rpm 三态探测,落 reports/plan-*.yaml)
.venv/bin/python main.py deps --dry-run    # 预期 RC=0,逐节点列出将补齐的包

# ② 真实补齐(逐台 dnf,连续失败 2 台即终止;内部自动做 rpm+ldd 双复验)
.venv/bin/python main.py deps              # 预期 RC=0;日志见 logs/deploy.log

# ③ 门禁与漂移复核(幂等回归)
.venv/bin/python main.py precheck          # 预期 RC=0,client_deps INFO
.venv/bin/python main.py drift             # 预期 RC=0,client_deps done
.venv/bin/python main.py deps              # 幂等:预期"依赖已全部满足,跳过"

3.6 验证

实测记录(2026-09-25)

时点 动作 结果
22:08 deps --dry-run RC=0,plan 落盘(dry_run: true),三节点各 6 包
22:10 precheck(deps 上线后、补包前) RC=1,三节点 client_deps BLOCK(门禁生效)
22:13 drift(补包前) RC=1,client_deps pending 3/3、18 包次(真漂移)
22:14–22:28 deps 真实执行 三节点 dnf 补齐 6 包;rpm 复验 3×6 全装;ldd 锚点真缺=0
22:28–22:33 复跑 deps/precheck/drift 全 RC=0:skipped / INFO / done
22:35 install --dry-run 回归 RC=0 skipped(既有流程无破坏)
22:40 三节点验证命令实测 NOTFOUND=0 RO ×3(判据修正生效)

证据:logs/deploy.log(22:08 起)、reports/plan-20260925-220822.yaml、 reports/precheck-*.md、reports/drift-*.md(22:33 档)。

3.7 回滚

  • 代码/配置:本轮 8 个文件备份于 backup/(.bak.20260925-215641 七件 + utils/ic_install.py.bak.20260925-223851),回滚 = 对应 .bak 覆盖还原后复跑 precheck;台账见 backup/README.md。
  • RPM:dnf remove motif libXmu libXp libXt mesa-libGLU libX11-xcb(或 dnf history undo <事务>)。 装包不覆盖任何既有文件;移除后 precheck 的 client_deps 恢复 BLOCK 提示。
  • 判据回滚后:三节点验证回到恒失败状态(既有缺陷复现),依赖 BLOCK 恢复。

3.8 风险说明

风险 说明 缓解
rpm 多包 rc 非固定 位掩码组合(实测缺包 rc=6,非单包的 1);初版按 rc=1 判定误报 unknown 已改为按文档化输出解析未装行,解析不出才 unknown;输出含声明外包名同样判 unknown
deps 不走全量门禁 有意设计:缺包 BLOCK 若挡住 deps 自身即自我死锁 deps 仅做配置校验 + 三态探测,unknown 一律中止
声明清单外的未知缺库 新环境可能出现配置未声明的缺失 ldd_anchor 复验兜底:真缺>0 即 RC=1 不放行;发现新缺库补进 packages
在线源版本漂移 dnf 走在线源,跨时间安装版本可能不一致 集群同构内网源可接受;离线 bundle 未做,登记为后续可选项
执行窗口未实时复核 22:14 执行依据 21:39 的 squeue 空,未在执行瞬间复核 已列入 3.3 前置条件;后续执行前须复核 squeue

3.9 扩容执行记录(2026-09-25 lsf-work-01/02/03,23 时档)

  • 新增 nodes.lsf_client 角色组(192.168.31.25-.27,Rocky 9.8,root 免密): deps 与通用预检查覆盖全角色组,install/patch 客户端验证仍只取 client—— 三台 /tools 未挂载(挂载属另工程、fstab 为红线本工程不动),挂载后再并入 client。
  • 配套修复 _ldd_true_missing:锚点不可见节点 WARN 跳过并明示,不再把 "锚点不存在"静默判为真缺=0(全部节点不可见则复验判失败)。
  • 实测(窗口:执行前实测三台 bjobs/squeue 均空): 22:59 deps --dry-run 仅 lsf 三台 pending → 22:59–23:02 真实补齐(各 6 包)→ rpm 复验 6 节点 × 6 包全装;ldd 复验 lsf 三台 WARN 跳过、Slurm 三台真缺=0 → 复跑 deps skipped(幂等)、precheck RC=0(六台口径,仅 lsf 三台各 1 条 firewalld inactive WARN)、drift RC=0(client_deps 6 节点 done)、 install --dry-run 回归 RC=0 skipped。
  • 证据:reports/plan-20260925-225913.yaml、logs/deploy.log(22:59 起)。

3.10 挂载接入与介质消费态判据修正(2026-09-25 23 时档)

  • /tools 挂载(lsf 三台;用户豁免 fstab 红线):经用户 2026-09-25 明确确认,向 192.168.31.25-.27 的 /etc/fstab 追加与 .18 相同条目 (192.168.31.249:/data/nfs/tools /tools nfs ro,hard,timeo=600,retrans=2,noatime,actimeo=30,_netdev 0 0) 并 mount;改前三份 fstab 备份于 backup/remote/<host>/etc/fstab.bak.20260925-232750。 实测三台 nfs4 ro、/tools/cadence/virtuoso/IC25.10.000 可见。
  • 角色并入:三台从 lsf_client 并入 client(install/patch 客户端验证扩为六台; 配置备份 config/ic25_install.yaml.bak.20260925-232814)。六台客户端验证实测 NOTFOUND=0 RO ×6(挂载复验通过,§3.2 判据在六台口径成立)。
  • 介质删除(用户操作,23:03–23:26):../IC25.10.000/ 全部 9 卷 tar(Base 5 + Hotfix 4) 被用户删除,需用时拷回。后果:回滚链降级——rollback --force 删目录后暂无法重装 Base 000;无补丁介质则 patch 不可再执行(当前 kit 12/12 不受影响,运行本体不依赖 tar)。
  • 消费态判据修正(probe_media/probe_patch_media,备份 ic_state.py.bak.20260925-233704): 安装/补丁已完成(done)而介质缺失 → done 并注明"已消费删除",门禁与漂移不再永久报红; 未完成时缺失仍 unknown 中止(无介质装不了,门禁照挡)。实测:precheck RC=0 (media INFO 登记)、drift RC=0、install/patch --dry-run 均 RC=0。

3.11 modulefile 真实化(跨工程,2026-09-26,关闭待办 #0)

  • 实施主体在 slurm_ins 工程(/opt/modulefiles 唯一来源红线,经其 --module-env 执行): families.cadence 占位换 virtuoso/IC25.10.000、渲染器新增 prepend 注入 26 目录 LD_LIBRARY_PATH;完整档案见 slurm_ins/docs/SOP.md §5.12、备份见其 docs/backup/。
  • 验收(本工程口径):有 Lmod 且挂 /tools 的四台(.18/.19/.20/.28)执行加载链 module load cadence virtuoso/IC25.10.000 后 ldd not found=0 (217 树内库闭合的终验判据);sinfo 正常、slurmd active、复跑幂等零变更。
  • 缺口登记:master .16/.17 无 /tools(不跑作业,仅影响其 module 工具可用); lsf 三台 .25–.27 未装 Lmod(rpm 依赖与 /tools 挂载均已就绪)。
  • 用户用法:作业脚本首行 source /etc/profile.d/zzz_site_lmod.sh,然后 module load cadence virtuoso/IC25.10.000(加载链,家族分层下不可单步)。

变更 4(2026-09-26):卸载 IC25.10.000 安装树(rollback --force)

4.1 背景

用户决定放弃 IC25.10.000("当前版本无法用于学习"),要求只删除安装树本体, 保留客户端 /tools 挂载、Lmod modulefile、31.29 FlexLM license 服务与 /opt/iscape (原话"只管删除,别的不管";替代版本另定)。触发条件:安装侧本已闭环 (六台客户端验证 NOTFOUND=0 RO),但该版本不适用于学习场景。

4.2 目标(可验证状态)

  • [x] /data/nfs/tools/cadence/virtuoso/IC25.10.000(约 33G)已删除
  • [x] 六台客户端 /tools 视图下该路径全部 ABSENT
  • [x] 父目录 /data/nfs/tools/cadence/virtuoso/ 保留(其内 1patch 文件非本次范围,未动)
  • [x] 范围外对象零改动:modulefile、六台 fstab 挂载、license 服务、/opt/iscape

4.3 前置条件

  • 只读预演 rollback --dry-run 通过(安全推导:install_dir 须等于 install_root/vendor/tool/version 四级拼接 + findmnt 实证非系统盘)
  • 六台客户端 squeue / bjobs 均为空(共享安装树,有作业不得动该节点)
  • 用户明确确认执行(高危不可逆,且介质已于 09-25 删除)

4.4 影响范围

NFS server 192.168.31.249 的 /data/nfs(安装树所在)+ 六台客户端只读视图; 不停服、无在跑作业;实测窗口约 10 秒。

4.5 分步操作(以实现体为准)

实现体:deployer.py(cmd_rollback)→ utils/ic_install.py(rollback → _sudo_rm_rf); 删除目标由 utils/ic_state.py(derive_install_targets)白名单推导,唯一。

步骤 1:只读预演(零变更)

.venv/bin/python main.py rollback --dry-run

预期:日志出现 【高危】回滚目标(推导): ['/data/nfs/tools/cadence/virtuoso/IC25.10.000'] 与 [dry-run] 将删除安装目录 …,RC=0,不产生任何变更。 失败判断:出现"回滚安全推导未通过"→ 停手,核对 config/ic25_install.yaml 的 install_root / install_dir / vendor / tool / version。

步骤 2:执行前门禁(六台作业空)

for h in 18 19 20 25 26 27; do printf "%s " "$h"; \
  ssh -o ConnectTimeout=6 -o BatchMode=yes root@192.168.31.$h \
  'echo "slurm=$(squeue -h 2>/dev/null|wc -l) lsf=$(bjobs -noheader 2>/dev/null|wc -l)"'; done

预期:六台均 slurm=0 lsf=0。任一非 0 → 停止,等作业结束再来。

步骤 3:执行删除(高危;长任务通道)

setsid nohup .venv/bin/python main.py rollback --force \
  > logs/rollback-$(date +%Y%m%d-%H%M%S).log 2>&1 < /dev/null &

等价底层动作(实现体按白名单推导后执行,目标为具体路径、非通配):

# 高危:删除安装目录(不可逆)
sudo -n rm -rf -- /data/nfs/tools/cadence/virtuoso/IC25.10.000

预期:日志 回滚完成:安装目录已删除,RC=0;实测耗时约 9 秒。 失败判断:返回非 0 或日志 回滚后仍存在 → 检查 sudo -n 免密与 NFS 写权限; 不重跑、不换参数(同一逻辑连续失败 2 次即终止)。

4.6 验证

test -e /data/nfs/tools/cadence/virtuoso/IC25.10.000 && echo EXISTS || echo GONE   # 预期 GONE
for h in 18 19 20 25 26 27; do printf "192.168.31.%s " "$h"; \
  ssh -o ConnectTimeout=6 -o BatchMode=yes root@192.168.31.$h \
  'test -e /tools/cadence/virtuoso/IC25.10.000 && echo PRESENT || echo ABSENT'; done

实测(2026-09-26 16:55):本地 GONE;.18/.19/.20/.25/.26/.27 六台全 ABSENT。 时档:预演 reports/plan-20260926-165153.yaml、执行 reports/plan-20260926-165512.yaml、 运行日志 logs/rollback-20260926-165512.log。

4.7 回滚

  • 不可回滚:Base/Hotfix 介质已于 2026-09-25 被用户删除(见 §3.10 与 backup/README.md 删除类动作),该版本无法重装;若需恢复须先取回介质再重跑 install (介质缺失时门禁按"未完成"判 unknown 中止)。
  • 纯删除动作,无 .bak 前置备份;已登记于 backup/README.md「删除类动作登记」。

4.8 风险说明

风险 实测情况 缓解
不可逆 介质已删,删后无法重装 IC25.10.000 执行前向用户明示并取得确认
半删残留 未发生——删除单次成功,实现体复查 remaining 为空 删除后强制复查目标存在性
modulefile 悬空 module load cadence virtuoso/IC25.10.000 将指向空路径而失败(条目与 /tools 挂载仍在) 按用户范围有意保留;换版本时由 slurm_ins 侧重新渲染
误删越界 未发生——目标经四级拼接 + findmnt 白名单推导;父目录及其内 1patch 未受影响 删除类动作一律走安全推导 + --force

来源:/home/rain/Documents/eda_tools_ins/Cadence/ic25_install_20260924/docs/SOP.md | 最后更新:2026-09-26 16:56(由 build/sync.py 同步,请勿在站点侧修改)