Skip to content

<fix>[network]: ZCF-3703 add ZNS attach skip hook#4007

Open
zstack-robot-2 wants to merge 5 commits into
5.5.22from
sync/shixin.ruan/shixin-ZCF-3703@@2
Open

<fix>[network]: ZCF-3703 add ZNS attach skip hook#4007
zstack-robot-2 wants to merge 5 commits into
5.5.22from
sync/shixin.ruan/shixin-ZCF-3703@@2

Conversation

@zstack-robot-2
Copy link
Copy Markdown
Collaborator

Summary

ZCF-3703: add a generic attach skip extension so ZNS L3 can accept legacy Flat DHCP attach API as a no-op.

Changes

  • Add NetworkServiceAttachExtensionPoint.
  • Let NetworkServiceApiInterceptor mark selected attach messages as skipAttach before generic duplicate DHCP validation.
  • Let L3BasicNetwork return a successful attach event without persisting refs when skipAttach is set.

Testing

  • mvn -pl header,network -DskipTests install

Related Jira: ZCF-3703

sync from gitlab !9900

ZCF-3703: allow ZNS to ignore Flat DHCP attach.

Change-Id: If8929ee4cc111825b42b688678bca81b3f08eed5
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 18, 2026

Review Change Stack

Walkthrough

新增 skipAttach 消息字段与访问器、定义 NetworkServiceAttachExtensionPoint 并在 NetworkServiceApiInterceptor 中通过 PluginRegistry 调用扩展点决定跳过挂载;L3BasicNetwork 在收到带 skipAttach 的消息时早期返回。另增 NetworkServiceProviderType 的 DHCPv6 开关,并调整 FlatDhcpBackend 的 IPv6 分配校验;新增 SDN DHCP 的 systemTags 与 ZNS 错误码常量。

变更

网络服务挂载跳过机制与 DHCPv6 分配控制

层级 / 文件 概要
消息契约扩展
header/src/main/java/org/zstack/header/network/service/APIAttachNetworkServiceToL3NetworkMsg.java
新增 skipAttach transient 布尔字段及 isSkipAttach() / setSkipAttach(boolean) 访问器,并导入 @APINoSee
扩展点接口定义
header/src/main/java/org/zstack/header/network/service/NetworkServiceAttachExtensionPoint.java
新增 NetworkServiceAttachExtensionPoint 接口,声明 boolean skipAttachNetworkService(APIAttachNetworkServiceToL3NetworkMsg msg) 方法。
拦截器级跳过判定
network/src/main/java/org/zstack/network/service/NetworkServiceApiInterceptor.java
注入 PluginRegistry;拦截 APIAttachNetworkServiceToL3NetworkMsg 时归一化并转换 networkServices,调用扩展点判断是否跳过;若任一扩展返回 true 则设置 msg.skipAttach 并提前返回;新增 normalizeNetworkServices(...) 并调整空判定逻辑。
处理器级跳过实现
network/src/main/java/org/zstack/network/l3/L3BasicNetwork.java
handle(APIAttachNetworkServiceToL3NetworkMsg) 中新增早期分支:当 msg.isSkipAttach() 为真时,重载 self、设置事件清单、发布事件并返回,绕过 attach/enable 工作流。
Provider DHCPv6 开关
header/src/main/java/org/zstack/header/network/service/NetworkServiceProviderType.java
新增 allocateDhcpv6ServerIp 字段与 isAllocateDhcpv6ServerIp() / setAllocateDhcpv6ServerIp(boolean) 方法。
Flat DHCP 后端 IPv6 校验
plugin/flatNetworkProvider/src/main/java/org/zstack/network/service/flat/FlatDhcpBackend.java
ipVersion 检查 DHCP server IP 可分配性,新增 isAllocateDhcpServerIp(l3Uuid, ipVersion),并在 validate(APIChangeL3NetworkDhcpIpAddressMsg) 中分别校验 IPv4/IPv6 字段。
SDN DHCP systemTags 写入
header/src/main/java/org/zstack/header/network/l3/SdnControllerEnableDHCPMsg.java, network/src/main/java/org/zstack/network/service/DhcpExtension.java
新增 systemTags 字段与访问器,DhcpExtension 在构造 SdnControllerEnableDHCPMsg 时设置该字段。
ZNS DHCP 错误码
utils/src/main/java/org/zstack/utils/clouderrorcode/CloudOperationsErrorCode.java
新增错误码注释与常量 ORG_ZSTACK_NETWORK_ZNS_10043 ~ ORG_ZSTACK_NETWORK_ZNS_10048。

Sequence Diagram(s):

sequenceDiagram
  participant Client
  participant NetworkServiceApiInterceptor
  participant PluginRegistry
  participant L3BasicNetwork
  participant EventBus
  Client->>NetworkServiceApiInterceptor: APIAttachNetworkServiceToL3NetworkMsg
  NetworkServiceApiInterceptor->>PluginRegistry: getExtensionPoints(NetworkServiceAttachExtensionPoint)
  NetworkServiceApiInterceptor->>PluginRegistry: skipAttachNetworkService(msg)
  PluginRegistry-->>NetworkServiceApiInterceptor: boolean result
  NetworkServiceApiInterceptor-->>L3BasicNetwork: forward msg (可能包含 skipAttach)
  L3BasicNetwork->>EventBus: publish APIAttachNetworkServiceToL3NetworkEvent (若 skipAttach)
Loading

🎯 4 (Complex) | ⏱️ ~45 minutes

🐰 网络服务挂载可跳过,
扩展点悄声说“放行”,
拦截器先行把门,处理器优雅退场,
DHCPv6 也加入了小小的规则,
小兔为此鼓掌庆祝 🎉

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed 标题遵循了 [scope]: 格式,包含了 JIRA 密钥 ZCF-3703,准确概括了PR的主要功能:添加ZNS附加跳过钩子。
Description check ✅ Passed PR描述清晰地关联了变更集内容,包括新增NetworkServiceAttachExtensionPoint、更新NetworkServiceApiInterceptor标记跳过消息、以及L3BasicNetwork返回成功事件的逻辑。
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ 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/shixin.ruan/shixin-ZCF-3703@@2

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.42.2)
utils/src/main/java/org/zstack/utils/clouderrorcode/CloudOperationsErrorCode.java

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

Copy link
Copy Markdown

@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)
header/src/main/java/org/zstack/header/network/service/NetworkServiceAttachExtensionPoint.java (1)

3-4: ⚡ Quick win

请为扩展点方法补充 Javadoc 约定。

Line 4 缺少接口方法说明,调用方和实现方很难统一“返回 true 的触发条件/副作用边界”。

✏️ 建议修改
 public interface NetworkServiceAttachExtensionPoint {
+    /**
+     * Decide whether current attach request should be treated as no-op.
+     *
+     * `@param` msg attach request message (already normalized by interceptor)
+     * `@return` true to skip attach workflow and return success event directly
+     */
     boolean skipAttachNetworkService(APIAttachNetworkServiceToL3NetworkMsg msg);
 }

As per coding guidelines "接口方法不应有多余的修饰符(例如 public),且必须配有有效的 Javadoc 注释。"

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@header/src/main/java/org/zstack/header/network/service/NetworkServiceAttachExtensionPoint.java`
around lines 3 - 4, 为接口 NetworkServiceAttachExtensionPoint 与其方法
skipAttachNetworkService(APIAttachNetworkServiceToL3NetworkMsg msg) 补充
Javadoc:在接口注释中简短描述该扩展点用途;在方法注释明确说明何时应返回 true(例如:实现方检测到应跳过附加且不会有副作用或已完成所需操作时返回
true)、返回 false 表示继续正常附加流程;声明实现方不得对 msg
做不可预期的可变更更改、应保证幂等性/线程安全(如适用)、任何异常应抛出或记录的约定以及调用方对返回值的期望和后续行为(调用方据此决定是否执行附加逻辑)。
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@network/src/main/java/org/zstack/network/service/NetworkServiceApiInterceptor.java`:
- Around line 42-45: For APIAttachNetworkServiceToL3NetworkMsg, trim
whitespace/newlines from the message's network service strings before performing
provider-type-to-UUID conversion and before calling skipAttachNetworkService:
obtain the values via attachMsg.getNetworkServices(), trim each element (and
ignore empty results), then pass the trimmed list to
convertNetworkProviderTypeToUuid and to the skipAttachNetworkService logic, and
finally use attachMsg.setNetworkServices(...) with the cleaned list so
leading/trailing spaces won't break matching.

---

Nitpick comments:
In
`@header/src/main/java/org/zstack/header/network/service/NetworkServiceAttachExtensionPoint.java`:
- Around line 3-4: 为接口 NetworkServiceAttachExtensionPoint 与其方法
skipAttachNetworkService(APIAttachNetworkServiceToL3NetworkMsg msg) 补充
Javadoc:在接口注释中简短描述该扩展点用途;在方法注释明确说明何时应返回 true(例如:实现方检测到应跳过附加且不会有副作用或已完成所需操作时返回
true)、返回 false 表示继续正常附加流程;声明实现方不得对 msg
做不可预期的可变更更改、应保证幂等性/线程安全(如适用)、任何异常应抛出或记录的约定以及调用方对返回值的期望和后续行为(调用方据此决定是否执行附加逻辑)。
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ 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: 9d9916c6-6ea5-4014-820c-eacdf4018029

📥 Commits

Reviewing files that changed from the base of the PR and between f83c595 and a455e0f.

📒 Files selected for processing (4)
  • header/src/main/java/org/zstack/header/network/service/APIAttachNetworkServiceToL3NetworkMsg.java
  • header/src/main/java/org/zstack/header/network/service/NetworkServiceAttachExtensionPoint.java
  • network/src/main/java/org/zstack/network/l3/L3BasicNetwork.java
  • network/src/main/java/org/zstack/network/service/NetworkServiceApiInterceptor.java

*/
@APIParam
private Map<String, List<String>> networkServices;
private transient boolean skipAttach;
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Comment from shixin.ruan:

是不是应该加@APINoSee

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Comment from shixin.ruan:

fixed in 3a61b56.\n\nDefect class: API surface hygiene.\nBefore: skipAttach was transient but still had no explicit API hiding annotation.\nAfter: added @APINoSee to skipAttach so this internal control flag is hidden from REST/API field exposure.\nValidation: mvn -pl header,network -DskipTests install passed.

Normalize attach network service provider keys and service names before provider conversion and skip extension checks.
Hide the internal skipAttach flag from API surface.

Resolves: ZCF-3703

Change-Id: Id6ff18d0bf5e86937c50a82721249055d3f76ade
@MatheMatrix MatheMatrix force-pushed the sync/shixin.ruan/shixin-ZCF-3703@@2 branch from 3a61b56 to fd6da83 Compare May 18, 2026 05:39
Copy link
Copy Markdown

@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

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@plugin/flatNetworkProvider/src/main/java/org/zstack/network/service/flat/FlatDhcpBackend.java`:
- Around line 997-1000: The method allocateDhcpIp currently returns null when
isAllocateDhcpServerIp(l3Uuid, ipVersion) is false which silently treats
“capability not supported” as a normal allocation failure; change this to
fail-fast by throwing a clear exception (e.g., an
OperationFailureException/CloudRuntimeException) when DHCP server IP allocation
is not supported for the given l3Uuid/ipVersion so callers like
afterAddIpRange() and FlatDhcpAcquireDhcpServerIpMsg will treat it as an
explicit error; keep isAllocateDhcpServerIp check but replace the null return
with a descriptive exception message stating DHCPv6 allocation is unsupported
for that L3 and IP version.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ 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: 9cf2c686-15c4-410f-96d8-968744a04020

📥 Commits

Reviewing files that changed from the base of the PR and between 3a61b56 and fd6da83.

📒 Files selected for processing (4)
  • header/src/main/java/org/zstack/header/network/service/APIAttachNetworkServiceToL3NetworkMsg.java
  • header/src/main/java/org/zstack/header/network/service/NetworkServiceProviderType.java
  • network/src/main/java/org/zstack/network/service/NetworkServiceApiInterceptor.java
  • plugin/flatNetworkProvider/src/main/java/org/zstack/network/service/flat/FlatDhcpBackend.java
🚧 Files skipped from review as they are similar to previous changes (2)
  • header/src/main/java/org/zstack/header/network/service/APIAttachNetworkServiceToL3NetworkMsg.java
  • network/src/main/java/org/zstack/network/service/NetworkServiceApiInterceptor.java

Comment on lines 997 to 1000
@Deferred
private String allocateDhcpIp(String l3Uuid, int ipVersion, boolean allocate_ip, String requiredIp, String excludedIp) {
if (!isAllocateDhcpServerIp(l3Uuid)) {
if (!isAllocateDhcpServerIp(l3Uuid, ipVersion)) {
return null;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

不要用 null 静默表示“不支持 DHCPv6 分配”。

这里把“不支持当前 IP 版本分配”折叠成 null 返回后,afterAddIpRange()FlatDhcpAcquireDhcpServerIpMsg 等现有调用方不会把它当成错误处理。这样一来,非 SLAAC 的 IPv6 range 可能成功走完整个流程,但 DHCPv6 server IP/tag 根本没有落下来,L3 会进入部分配置状态。建议把 capability 不支持与普通分配失败区分开,并在 attach / add-range 这类入口上显式报错。

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@plugin/flatNetworkProvider/src/main/java/org/zstack/network/service/flat/FlatDhcpBackend.java`
around lines 997 - 1000, The method allocateDhcpIp currently returns null when
isAllocateDhcpServerIp(l3Uuid, ipVersion) is false which silently treats
“capability not supported” as a normal allocation failure; change this to
fail-fast by throwing a clear exception (e.g., an
OperationFailureException/CloudRuntimeException) when DHCP server IP allocation
is not supported for the given l3Uuid/ipVersion so callers like
afterAddIpRange() and FlatDhcpAcquireDhcpServerIpMsg will treat it as an
explicit error; keep isAllocateDhcpServerIp check but replace the null return
with a descriptive exception message stating DHCPv6 allocation is unsupported
for that L3 and IP version.

shixin.ruan added 2 commits May 18, 2026 16:57
Resolves: ZCF-3703

Change-Id: I8b002e1c0b7e0535df0803a8107e9b4ebbdadf21
Split ZNS DHCP error codes used by premium DHCP paths.\nAdd i18n mappings for the new concrete error templates.

Resolves: ZCF-3703

Change-Id: I11bf0fc6df8cf5a5e1ae24af958c5ca3712b4347
Copy link
Copy Markdown

@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.

🧹 Nitpick comments (2)
header/src/main/java/org/zstack/header/network/l3/SdnControllerEnableDHCPMsg.java (1)

30-35: ⚡ Quick win

建议对 systemTags 做防御性拷贝,避免消息负载被外部可变引用污染。

当前 getter/setter 直接暴露并持有同一 List 引用,后续外部修改可能影响已构造的消息内容。

♻️ 建议修改
 public List<String> getSystemTags() {
-    return systemTags;
+    return systemTags == null ? null : new java.util.ArrayList<>(systemTags);
 }

 public void setSystemTags(List<String> systemTags) {
-    this.systemTags = systemTags;
+    this.systemTags = systemTags == null ? null : new java.util.ArrayList<>(systemTags);
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@header/src/main/java/org/zstack/header/network/l3/SdnControllerEnableDHCPMsg.java`
around lines 30 - 35, The getter and setter for the field systemTags in
SdnControllerEnableDHCPMsg expose the internal List reference; change
setSystemTags(List<String>) to defensively copy the incoming list (e.g.
this.systemTags = incoming == null ? null : new ArrayList<>(incoming)) and
change getSystemTags() to return either an unmodifiable copy or a defensive copy
(e.g. return systemTags == null ? null :
Collections.unmodifiableList(systemTags) or new ArrayList<>(systemTags)), and
ensure null-safety in both methods so external mutations cannot affect the
message's internal state.
utils/src/main/java/org/zstack/utils/clouderrorcode/CloudOperationsErrorCode.java (1)

12127-12132: ⚡ Quick win

统一错误码注释的首字母大写。

第 12127 行和第 12132 行的注释以小写 "failed" 开头,而第 12128-12131 行以大写 "ZNS" 开头。这与上方已有注释(第 12124-12126 行均以大写开头)不一致,也造成新增注释内部风格不统一。建议将第 12127 和 12132 行改为大写开头以保持一致性。

♻️ 建议的修复
-    // 10043 failed to allocate DHCPv4 server IP in ZNS DHCP helper
+    // 10043 Failed to allocate DHCPv4 server IP in ZNS DHCP helper
     // 10044 ZNS DHCP enable has no eligible IpRange
     // 10045 ZNS DHCP enable has no Cloud-reserved DHCPv4 server IP
     // 10046 ZNS DHCP 409 fallback GET returned empty
     // 10047 ZNS DHCP update has no Cloud-reserved DHCPv4 server IP
-    // 10048 failed to allocate DHCPv4 server IP in ZNS DHCP backend
+    // 10048 Failed to allocate DHCPv4 server IP in ZNS DHCP backend
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@utils/src/main/java/org/zstack/utils/clouderrorcode/CloudOperationsErrorCode.java`
around lines 12127 - 12132, The two comment lines in
CloudOperationsErrorCode.java that start with "failed to allocate DHCPv4 server
IP in ZNS DHCP helper" and "failed to allocate DHCPv4 server IP in ZNS DHCP
backend" should have their initial word capitalized to match surrounding
comments; update those strings to start with "Failed" so all error-code comment
entries (including the existing "ZNS ..." lines) use a consistent initial
capital letter.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In
`@header/src/main/java/org/zstack/header/network/l3/SdnControllerEnableDHCPMsg.java`:
- Around line 30-35: The getter and setter for the field systemTags in
SdnControllerEnableDHCPMsg expose the internal List reference; change
setSystemTags(List<String>) to defensively copy the incoming list (e.g.
this.systemTags = incoming == null ? null : new ArrayList<>(incoming)) and
change getSystemTags() to return either an unmodifiable copy or a defensive copy
(e.g. return systemTags == null ? null :
Collections.unmodifiableList(systemTags) or new ArrayList<>(systemTags)), and
ensure null-safety in both methods so external mutations cannot affect the
message's internal state.

In
`@utils/src/main/java/org/zstack/utils/clouderrorcode/CloudOperationsErrorCode.java`:
- Around line 12127-12132: The two comment lines in
CloudOperationsErrorCode.java that start with "failed to allocate DHCPv4 server
IP in ZNS DHCP helper" and "failed to allocate DHCPv4 server IP in ZNS DHCP
backend" should have their initial word capitalized to match surrounding
comments; update those strings to start with "Failed" so all error-code comment
entries (including the existing "ZNS ..." lines) use a consistent initial
capital letter.

ℹ️ 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: 599e46e6-3dcd-428b-baf1-0a44a02765b9

📥 Commits

Reviewing files that changed from the base of the PR and between fd6da83 and 5dc68e1.

⛔ Files ignored due to path filters (2)
  • conf/i18n/globalErrorCodeMapping/global-error-en_US.json is excluded by !**/*.json
  • conf/i18n/globalErrorCodeMapping/global-error-zh_CN.json is excluded by !**/*.json
📒 Files selected for processing (3)
  • header/src/main/java/org/zstack/header/network/l3/SdnControllerEnableDHCPMsg.java
  • network/src/main/java/org/zstack/network/service/DhcpExtension.java
  • utils/src/main/java/org/zstack/utils/clouderrorcode/CloudOperationsErrorCode.java

JIRA: ZCF-3703

Remove the duplicate systemTags field from SdnControllerEnableDHCPMsg.
NeedReplyMessage already owns systemTags, so redeclaring it makes Gson
fail while CloudBus logs the message before sending it to the ZNS DHCP
handler.

Change-Id: I4546348c9fd45004e0f9b9c823f9cccec9ad4774
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.

5 participants