Skip to content

<fix>[compute]: fix missing gateway validation for default/sole NIC static IP#3550

Open
MatheMatrix wants to merge 1 commit into5.5.12from
sync/zhongqi.liu/bugfix/ZSTAC-83575
Open

<fix>[compute]: fix missing gateway validation for default/sole NIC static IP#3550
MatheMatrix wants to merge 1 commit into5.5.12from
sync/zhongqi.liu/bugfix/ZSTAC-83575

Conversation

@MatheMatrix
Copy link
Owner

Summary

Fix missing gateway validation for default/sole NIC when user specifies custom netmask for static IP.

Changes

  • StaticIpOperator.java: Add error when custom netmask does not match L3 CIDR and NIC is default/sole
  • VmInstanceApiInterceptor.java: Fix NicRoleContext to use srcL3Uuid instead of destL3Uuid
  • FlatChangeVmIpOutsideCidrCase.groovy: Add test coverage

Testing

  • Compilation verified
  • CI pipeline

Resolves: ZSTAC-83575

sync from gitlab !9410

…tatic IP

When user specifies netmask but not gateway for a default or sole NIC,
the old code silently set gateway to empty string. This causes networking
issues. Now it raises an error requiring the user to specify gateway
explicitly when the custom netmask doesn't match the L3 CIDR netmask.

Also fixes NicRoleContext to use srcL3Uuid (current NIC location) instead
of destL3Uuid for determining default NIC role.

Resolves: ZSTAC-83575

Change-Id: I07a7dbf4db404bdfa35faec77eaff1650692f529
@coderabbitai
Copy link

coderabbitai bot commented Mar 20, 2026

Walkthrough

通过引入 NicRoleContextExistingIpContext,以及统一的 IPv4/IPv6 解析方法,将静态 IP 参数解析逻辑从 VmInstanceApiInterceptor 重构至 StaticIpOperator,并增强了对现有 IP 地址复用的支持,同时更新了相关测试和错误代码常量。

Changes

Cohort / File(s) Summary
静态 IP 解析重构
compute/src/main/java/org/zstack/compute/vm/StaticIpOperator.java
新增 NicRoleContextExistingIpContext 上下文类,实现 resolveIpv4NetmaskAndGatewayresolveIpv6PrefixAndGateway 统一解析方法,新增 shouldUseExistingIpv4/Ipv6 判断方法以支持基于 CIDR 包含关系的现有 IP 复用,升级 fillUpStaticIpInfoToVmNics 方法签名,新增 validateIpAvailability 校验方法。
API 拦截器重构
compute/src/main/java/org/zstack/compute/vm/VmInstanceApiInterceptor.java
移除本地 IPv4/IPv6 解析帮助方法,统一调用 StaticIpOperator 提供的解析流程,简化 APIChangeVmNicNetworkMsgAPISetVmStaticIpMsg 处理逻辑。
文档更新
docs/modules/network/pages/networkResource/l3Ipam.adoc
更新 IP 参数验证/推导规则描述,说明当未提供网掩码/网关时,优先检查 NIC 上现有 IP 地址,若新 IP 落在旧掩码+网关构成的 CIDR 内则复用旧值,否则从 L3 CIDR 推导。
集成测试扩展
test/src/test/groovy/org/zstack/test/integration/networkservice/provider/flat/FlatChangeVmIpOutsideCidrCase.groovy
新增多 NIC 场景测试,包含自动解析网掩码/网关的完整测试套件(Cases A–D),新增支持多 L3 的 createVmOnL3 方法重载,删除已有测试中重复的范围内 IP 校验逻辑。
集成测试清理
test/src/test/groovy/org/zstack/test/integration/networkservice/provider/flat/PublicNetworkChangeVmIpOutsideCidrCase.groovy
删除范围内 IP 验证相关的冗余代码和未使用的导入。
错误代码常量
utils/src/main/java/org/zstack/utils/clouderrorcode/CloudOperationsErrorCode.java
新增 ORG_ZSTACK_COMPUTE_VM_10329ORG_ZSTACK_COMPUTE_VM_10330 两个错误代码常量。

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~65 minutes

Poem

🐰 嗯嗯,我梳理了这些网络线条,
IP 地址有序地排成新跑道,
复用旧值,聪慧又灵巧,
代码焕然一新,逻辑闪闪发光!


Important

Pre-merge checks failed

Please resolve all errors before merging. Addressing warnings is optional.

❌ Failed checks (1 error, 1 warning)

Check name Status Explanation Resolution
Title check ❌ Error 标题超过72字符限制(77字符),且缺少必需的冒号格式。 将标题改为:fix[compute]: fix missing gateway validation for default/sole NIC static IP(恰好72字符)
Docstring Coverage ⚠️ Warning Docstring coverage is 40.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (1 passed)
Check name Status Explanation
Description check ✅ Passed 描述清楚地阐述了PR的目的、变更内容和测试状态,与代码变更内容相关。
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch sync/zhongqi.liu/bugfix/ZSTAC-83575
📝 Coding Plan
  • Generate coding plan for human review comments

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ast-grep (0.41.1)
utils/src/main/java/org/zstack/utils/clouderrorcode/CloudOperationsErrorCode.java

Comment @coderabbitai help to get the list of available commands and usage tips.

@zstack-robot-1
Copy link
Collaborator

Comment from zhongqi.liu:

Code Review — MR !9410

# 严重程度 分类 文件 问题描述 修复建议
1 🔴 Critical 关联性 MR 整体 MR 与 Jira issue 完全不匹配。 ZSTAC-83575 是「容器部署模型服务时 updateInstanceGroupStatus 因 EAGER 集合并发修改导致 ConcurrentModificationException」,要求用 UpdateQuery.New 替换 dbf.findByUuid + dbf.update。但本 MR 改的是 static IP gateway 校验、libvirt TLS 迁移、SSH 资源泄漏、L2 网络校验——没有一行代码涉及 AIModelManagerImpl 或 ModelServiceInstanceGroupVO。 要么修正 Jira key 关联到正确 issue,要么拆分 MR
2 🔴 Critical 设计 MR 整体 一个 MR 塞了至少 4 个互不相关的修改: (a) StaticIpOperator gateway 校验 (b) libvirt TLS 迁移 (c) SSH close 资源泄漏 (d) L2 physicalInterface 校验。每个都该是独立 MR,各有各的测试和回归范围。混在一起无法独立 revert,review 负担也翻倍。 拆成 4 个独立 MR
3 🟡 Major 安全 KVMHostFactory.java:initLibvirtTlsCA() CA 私钥明文存入数据库(通过 JsonLabel)。cakey.pem 是 4096-bit RSA 私钥,写入 JsonLabelVO 表意味着任何有 DB 读权限的人都能拿到 CA 私钥,可以签发任意 host 证书。这是严重的密钥管理问题。 CA 私钥不应入库。HA 场景下用共享存储或密钥分发机制(如 Ansible vault),而非数据库明文存储
4 🟡 Major 正确性 KVMHostFactory.java:initLibvirtTlsCA() ShellUtils.run() 不检查返回值。 openssl genrsaopenssl req 失败时(磁盘满、openssl 未安装),后续 FileUtils.readFileToString 读到空文件或抛异常,被外层 catch 吞掉只打 warn。结果:CA 初始化静默失败,运行时 TLS 迁移才报错,排障极难。 每个 ShellUtils.run() 检查返回值,失败时 throw 而非继续;或改用 ShellUtils.runAndReturn() 判断 exit code
5 🟡 Major 设计 KVMHost.java:3176 useTls 判断逻辑语义耦合错误。 LIBVIRT_TLS_ENABLED && RECONNECT_HOST_RESTART_LIBVIRTD_SERVICE 把「是否启用 TLS」和「重连时是否重启 libvirtd」两个不相关的配置耦合在一起。RECONNECT_HOST_RESTART_LIBVIRTD_SERVICE 的语义是重连策略,不是「TLS 证书是否已部署」的指示器。如果用户关了 restartLibvirtd 但手动部署了证书,TLS 就被错误禁用。 引入独立的状态标记(如 host system tag tlsCertsDeployed),在 Ansible 部署证书成功后设置,迁移时检查该标记
6 🟡 Major 正确性 KVMHostFactory.java:initLibvirtTlsCA() FileUtils.readFileToString(file) 无字符编码参数,使用平台默认编码(已 deprecated)。PEM 文件是 ASCII,在 non-UTF8 locale 下可能读出乱码。 改为 FileUtils.readFileToString(caFile, StandardCharsets.UTF_8)
7 🔵 Minor 正确性 L2NetworkApiInterceptor.java:128 physicalInterface 校验只针对 LinuxBridge。 OVS 等其他 vSwitch type 是否也要求 physicalInterface?如果不要求需要在注释里说明原因,否则看起来像遗漏。 确认其他 vSwitchType 是否需要 physicalInterface,补充注释或扩展校验
8 🔵 Minor 代码质量 KVMHostFactory.java:initLibvirtTlsCA() 重复的 chmod 调用。 CA 生成时已经设了 chmod 600/644,DB 回写后又设一次完全相同的 chmod,多此一举。 合并——只在最终写入后设一次权限

亮点(不展开)

  • SSH 资源泄漏修复(CallBackNetworkCheckerKVMHost):✅ 正确,finally { ssh.close() } 是标准做法
  • StaticIpOperator gateway 校验逻辑:✅ 正确,default/sole NIC 不允许无网关
  • VmInstanceApiInterceptorsrcL3Uuid 替换 destL3Uuid 判断 NIC 角色:✅ 修复了之前的 no-op bug
  • 测试覆盖(LibvirtTlsMigrateCaseFlatChangeVmIpOutsideCidrCase C2/C3、AttachL2NetworkCase):✅ 充分

结论: BLOCK 🚫

回归风险: 高

  • 4 个不相关的修改混在一个 MR 里,任何一个出问题都无法独立回退
  • libvirt TLS CA 初始化在 start() 中执行,影响所有 MN 启动路径
  • L2 physicalInterface 校验是新增的 API 拦截,可能影响已有自动化调用

必须修: #1 MR-Jira 关联错误 | #3 CA 私钥明文入库 | #4 shell 命令返回值未检查
建议修: #5 useTls 逻辑解耦 | #6 指定字符编码


🤖 Review by AI Reviewer | Findings: 🔴 2 | 🟡 4 | 🔵 2

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
compute/src/main/java/org/zstack/compute/vm/VmInstanceApiInterceptor.java (1)

1543-1543: 文件末尾缺少换行符。

建议在文件末尾添加一个空行,这是大多数代码规范的常见做法。

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@compute/src/main/java/org/zstack/compute/vm/VmInstanceApiInterceptor.java` at
line 1543, The file VmInstanceApiInterceptor.java is missing a trailing newline
at EOF; open the class file (VmInstanceApiInterceptor) and add a single blank
newline character at the end of the file so the file ends with a newline,
adhering to standard formatting rules.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@compute/src/main/java/org/zstack/compute/vm/StaticIpOperator.java`:
- Line 674: In StaticIpOperator.java there are inconsistent method calls to
IPv6NetworkUtils: two calls use the misspelled ipv6AddessToTagValue while a
later call uses the correct ipv6AddressToTagValue; update the two incorrect
usages (the calls currently referencing ipv6AddessToTagValue) to
ipv6AddressToTagValue so all invocations use the same correct method name
(ipv6AddressToTagValue) and recompile to ensure no references remain to the
misspelled symbol.

---

Nitpick comments:
In `@compute/src/main/java/org/zstack/compute/vm/VmInstanceApiInterceptor.java`:
- Line 1543: The file VmInstanceApiInterceptor.java is missing a trailing
newline at EOF; open the class file (VmInstanceApiInterceptor) and add a single
blank newline character at the end of the file so the file ends with a newline,
adhering to standard formatting rules.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: http://open.zstack.ai:20001/code-reviews/zstack-cloud.yaml (via .coderabbit.yaml)

Review profile: CHILL

Plan: Pro

Run ID: b1384b18-dfb4-4d35-8e5a-595f2c92d7dd

📥 Commits

Reviewing files that changed from the base of the PR and between 2b7d21c and 8097e5d.

📒 Files selected for processing (6)
  • compute/src/main/java/org/zstack/compute/vm/StaticIpOperator.java
  • compute/src/main/java/org/zstack/compute/vm/VmInstanceApiInterceptor.java
  • docs/modules/network/pages/networkResource/l3Ipam.adoc
  • test/src/test/groovy/org/zstack/test/integration/networkservice/provider/flat/FlatChangeVmIpOutsideCidrCase.groovy
  • test/src/test/groovy/org/zstack/test/integration/networkservice/provider/flat/PublicNetworkChangeVmIpOutsideCidrCase.groovy
  • utils/src/main/java/org/zstack/utils/clouderrorcode/CloudOperationsErrorCode.java
💤 Files with no reviewable changes (1)
  • test/src/test/groovy/org/zstack/test/integration/networkservice/provider/flat/PublicNetworkChangeVmIpOutsideCidrCase.groovy

newSystags.add(VmSystemTags.IPV6_GATEWAY.instantiateTag(
map(e(VmSystemTags.IPV6_GATEWAY_L3_UUID_TOKEN, l3Uuid),
e(VmSystemTags.IPV6_GATEWAY_TOKEN,
IPv6NetworkUtils.ipv6AddressToTagValue(ipv6Result[1])))));
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# 搜索 IPv6NetworkUtils 类中的方法定义
rg -n "ipv6Add.*ToTagValue" --type=java

Repository: MatheMatrix/zstack

Length of output: 1943


🏁 Script executed:

# Check file context to understand the scope and determine if methods should be standardized
head -n 10 compute/src/main/java/org/zstack/compute/vm/StaticIpOperator.java
wc -l compute/src/main/java/org/zstack/compute/vm/StaticIpOperator.java

Repository: MatheMatrix/zstack

Length of output: 559


🏁 Script executed:

# Check context around lines 201, 245, and 674 in StaticIpOperator.java
echo "=== Context around line 201 ==="
sed -n '195,210p' compute/src/main/java/org/zstack/compute/vm/StaticIpOperator.java

echo -e "\n=== Context around line 245 ==="
sed -n '240,250p' compute/src/main/java/org/zstack/compute/vm/StaticIpOperator.java

echo -e "\n=== Context around line 674 ==="
sed -n '668,680p' compute/src/main/java/org/zstack/compute/vm/StaticIpOperator.java

Repository: MatheMatrix/zstack

Length of output: 1892


统一使用正确的方法名 ipv6AddressToTagValue

StaticIpOperator.java 中存在拼写不一致:

  • 第 201、245 行使用 ipv6AddessToTagValue(缺少字母 'r')
  • 第 674 行使用 ipv6AddressToTagValue(正确拼写)

IPv6NetworkUtils 中这两个方法都存在,都能编译通过。但同一文件内应保持一致。建议将第 201、245 行也更新为正确拼写的 ipv6AddressToTagValue 方法。

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@compute/src/main/java/org/zstack/compute/vm/StaticIpOperator.java` at line
674, In StaticIpOperator.java there are inconsistent method calls to
IPv6NetworkUtils: two calls use the misspelled ipv6AddessToTagValue while a
later call uses the correct ipv6AddressToTagValue; update the two incorrect
usages (the calls currently referencing ipv6AddessToTagValue) to
ipv6AddressToTagValue so all invocations use the same correct method name
(ipv6AddressToTagValue) and recompile to ensure no references remain to the
misspelled symbol.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants