Skip to content

<feature>[utils]: Network group high availability strategy#3897

Open
ZStack-Robot wants to merge 1 commit into5.5.22from
sync/haoyu.ding/fv-81413@@3
Open

<feature>[utils]: Network group high availability strategy#3897
ZStack-Robot wants to merge 1 commit into5.5.22from
sync/haoyu.ding/fv-81413@@3

Conversation

@ZStack-Robot
Copy link
Copy Markdown
Collaborator

DBImpact

Resolves: ZSTAC-81413

Change-Id: I6a7574656467636e686377756f716d67707a7063

sync from gitlab !9779

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 7, 2026

Review Change Stack
No actionable comments were generated in the recent review. 🎉

ℹ️ Recent 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: f8078b8d-2764-490a-a7c3-ae2e6283dcfa

📥 Commits

Reviewing files that changed from the base of the PR and between 3734fad and 96fe476.

⛔ Files ignored due to path filters (12)
  • sdk/src/main/java/SourceClassMap.java is excluded by !sdk/**
  • sdk/src/main/java/org/zstack/sdk/ChangeHaNetworkGroupStateAction.java is excluded by !sdk/**
  • sdk/src/main/java/org/zstack/sdk/ChangeHaNetworkGroupStateResult.java is excluded by !sdk/**
  • sdk/src/main/java/org/zstack/sdk/CreateHaNetworkGroupAction.java is excluded by !sdk/**
  • sdk/src/main/java/org/zstack/sdk/CreateHaNetworkGroupResult.java is excluded by !sdk/**
  • sdk/src/main/java/org/zstack/sdk/DeleteHaNetworkGroupAction.java is excluded by !sdk/**
  • sdk/src/main/java/org/zstack/sdk/DeleteHaNetworkGroupResult.java is excluded by !sdk/**
  • sdk/src/main/java/org/zstack/sdk/HaNetworkGroupInventory.java is excluded by !sdk/**
  • sdk/src/main/java/org/zstack/sdk/QueryHaNetworkGroupAction.java is excluded by !sdk/**
  • sdk/src/main/java/org/zstack/sdk/QueryHaNetworkGroupResult.java is excluded by !sdk/**
  • sdk/src/main/java/org/zstack/sdk/UpdateHaNetworkGroupAction.java is excluded by !sdk/**
  • sdk/src/main/java/org/zstack/sdk/UpdateHaNetworkGroupResult.java is excluded by !sdk/**
📒 Files selected for processing (9)
  • conf/db/upgrade/V5.5.22__schema.sql
  • plugin/kvm/src/main/java/org/zstack/kvm/KVMAgentCommands.java
  • plugin/kvm/src/main/java/org/zstack/kvm/KVMConstant.java
  • simulator/simulatorImpl/src/main/java/org/zstack/simulator/kvm/KVMSimulatorConfig.java
  • simulator/simulatorImpl/src/main/java/org/zstack/simulator/kvm/KVMSimulatorController.java
  • testlib/src/main/java/org/zstack/testlib/ApiHelper.groovy
  • testlib/src/main/java/org/zstack/testlib/EnvSpec.groovy
  • testlib/src/main/java/org/zstack/testlib/KVMSimulator.groovy
  • utils/src/main/java/org/zstack/utils/clouderrorcode/CloudOperationsErrorCode.java
✅ Files skipped from review due to trivial changes (3)
  • plugin/kvm/src/main/java/org/zstack/kvm/KVMConstant.java
  • utils/src/main/java/org/zstack/utils/clouderrorcode/CloudOperationsErrorCode.java
  • conf/db/upgrade/V5.5.22__schema.sql
🚧 Files skipped from review as they are similar to previous changes (5)
  • simulator/simulatorImpl/src/main/java/org/zstack/simulator/kvm/KVMSimulatorController.java
  • testlib/src/main/java/org/zstack/testlib/EnvSpec.groovy
  • testlib/src/main/java/org/zstack/testlib/KVMSimulator.groovy
  • testlib/src/main/java/org/zstack/testlib/ApiHelper.groovy
  • simulator/simulatorImpl/src/main/java/org/zstack/simulator/kvm/KVMSimulatorConfig.java

Walkthrough

新增 HA 网络组持久化表与字段,扩展 KVM 代理命令和路由常量,添加模拟器端点与内存命令队列,更新测试帮助器以跟踪 API 路径,并新增一组 HA 错误码常量。

Changes

HA网络组支持

Layer / File(s) Summary
数据库模式
conf/db/upgrade/V5.5.22__schema.sql
为 ModelVO/ModelServiceRefVO 增加字段并回填 createDate;创建 HaNetworkGroupVOHaNetworkGroupL3NetworkRefVOHostHaNetworkGroupStatusVOHaNetworkGroupGlobalConfigVersionVO 表并初始化全局版本。
代理命令定义
plugin/kvm/src/main/java/org/zstack/kvm/KVMAgentCommands.java
新增 SetupVmHaEnabledMetadataLiveCmdReconcileVmHaEnabledMetadataLiveCmd@GrayVersion("5.5.22")),并在 StartVmCmd 中新增可空字段 enableHa 及访问器。
端点常量
plugin/kvm/src/main/java/org/zstack/kvm/KVMConstant.java
新增三条 KVM 路由常量:HA 元数据设置、协调和网络组同步。
错误码常量
utils/src/main/java/org/zstack/utils/clouderrorcode/CloudOperationsErrorCode.java
插入 HA 错误码常量 ORG_ZSTACK_HA_10019ORG_ZSTACK_HA_10036
模拟器集成
simulator/.../KVMSimulatorConfig.java, simulator/.../KVMSimulatorController.java, testlib/.../KVMSimulator.groovy
在模拟器配置中记录三个命令/请求 List;在控制器中添加三个 POST 端点以反序列化或记录请求体并追加到同步列表;注册模拟器路由返回 AgentResponse
测试支持
testlib/.../ApiHelper.groovy, testlib/.../EnvSpec.groovy
五个 HA 网络组 API helper 方法改为 OWNER_FIRST 委托闭包并在 apipath 模式下跟踪 API 路径;EnvSpec 的删除白名单新增 HaNetworkGroupGlobalConfigVersionVO

Sequence Diagram(s)

sequenceDiagram
  participant Agent as KVM Agent
  participant Simulator as KVMSimulatorController
  participant Config as KVMSimulatorConfig
  Agent->>Simulator: POST /setup-ha-enabled-metadata
  Simulator->>Config: append SetupVmHaEnabledMetadataLiveCmd (synchronized)
  Simulator->>Agent: AgentResponse
  Agent->>Simulator: POST /reconcile-ha-enabled-metadata
  Simulator->>Config: append ReconcileVmHaEnabledMetadataLiveCmd (synchronized)
  Simulator->>Agent: AgentResponse
  Agent->>Simulator: POST /ha-network-group/sync
  Simulator->>Config: append sync command string (synchronized)
  Simulator->>Agent: AgentResponse
Loading

🎯 3 (Moderate) | ⏱️ ~20 minutes

🐰 新表列队静又稳,端点应答列成行,

命令入队日志明明,测试追路步步详,
错误码排整齐,HA 功能慢慢长。

🚥 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 The PR title follows the required format [type][scope]: description and is 58 characters, within the 72-character limit.
Description check ✅ Passed The PR description references JIRA ticket ZSTAC-81413, mentions database impact, and indicates this syncs from GitLab. It is related to the changeset about HA network group functionality.
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/haoyu.ding/fv-81413@@3

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.1)
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: 2

🧹 Nitpick comments (1)
testlib/src/main/java/org/zstack/testlib/ApiHelper.groovy (1)

5663-5687: 🏗️ Heavy lift

抽取通用 apipath 调用模板,避免 5 处复制逻辑后续漂移

当前 apiId 补齐、ApiPathTracker 创建、a.call()Test.apiPaths 写入完全重复;后续修改容易漏改一处。建议提取成统一 helper。

♻️ 可参考的重构方向
+    private def callWithApiPathTracking(def a) {
+        if (System.getProperty("apipath") != null) {
+            if (a.apiId == null) {
+                a.apiId = Platform.uuid
+            }
+            def tracker = new ApiPathTracker(a.apiId)
+            def out = errorOut(a.call())
+            def path = tracker.getApiPath()
+            if (!path.isEmpty()) {
+                Test.apiPaths[a.class.name] = path.join(" --->\n")
+            }
+            return out
+        }
+        return errorOut(a.call())
+    }

然后每个方法收敛为:

-        if (System.getProperty("apipath") != null) {
-            ...
-        } else {
-            return errorOut(a.call())
-        }
+        return callWithApiPathTracking(a)

Also applies to: 9686-9710, 14870-14894, 31780-31795, 45201-45216

🤖 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 `@testlib/src/main/java/org/zstack/testlib/ApiHelper.groovy` around lines 5663
- 5687, Extract the repeated apipath handling into a single helper (e.g., a
private method like handleApiCall(Action a) or wrapApiCall) and replace the
duplicated blocks in methods such as changeHaNetworkGroupState by calling that
helper; the helper should: ensure a.apiId is set (Platform.uuid when null),
instantiate ApiPathTracker with a.apiId, invoke a.call() through errorOut,
record the path into Test.apiPaths keyed by a.class.name when non-empty, and
return the errorOut result—replace the duplicated logic in other locations (the
other listed ranges) to call this new helper and remove the inline duplication.
🤖 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 `@conf/db/upgrade/V5.5.22__schema.sql`:
- Around line 8-9: Replace the invalid zero-datetime defaults with
CURRENT_TIMESTAMP: update the column definitions that use `DEFAULT '0000-00-00
00:00:00'` (e.g., `lastOpDate`, `createDate` and the other two occurrences) to
use `DEFAULT CURRENT_TIMESTAMP` (and keep `ON UPDATE CURRENT_TIMESTAMP` only on
columns that should auto-update, e.g., `lastOpDate`), ensuring the NOT NULL
semantics remain intact so the DDL will succeed in strict SQL modes.

In
`@utils/src/main/java/org/zstack/utils/clouderrorcode/CloudOperationsErrorCode.java`:
- Around line 1875-1918: The new constants ORG_ZSTACK_HA_10019 through
ORG_ZSTACK_HA_10040 in CloudOperationsErrorCode are declared but lack message
definitions and are not referenced; either add message entries for each code in
the errorCode resource files and wire them into the ErrorCode/ResourceLoader
mechanism, then replace placeholder or create usage sites in business logic to
throw or return these codes (search for usages patterns like
ErrorCode/CLOUD_OPERATION_* or methods that create ErrorCode instances) or
remove the unused constants; if they are intended as reserved, add a clear
Javadoc comment on the constants explaining their planned purpose and why they
are unused.

---

Nitpick comments:
In `@testlib/src/main/java/org/zstack/testlib/ApiHelper.groovy`:
- Around line 5663-5687: Extract the repeated apipath handling into a single
helper (e.g., a private method like handleApiCall(Action a) or wrapApiCall) and
replace the duplicated blocks in methods such as changeHaNetworkGroupState by
calling that helper; the helper should: ensure a.apiId is set (Platform.uuid
when null), instantiate ApiPathTracker with a.apiId, invoke a.call() through
errorOut, record the path into Test.apiPaths keyed by a.class.name when
non-empty, and return the errorOut result—replace the duplicated logic in other
locations (the other listed ranges) to call this new helper and remove the
inline duplication.
🪄 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: 1451bf12-1c77-4c28-b4dc-25391e49b304

📥 Commits

Reviewing files that changed from the base of the PR and between 18b0d53 and db04ee4.

⛔ Files ignored due to path filters (12)
  • sdk/src/main/java/SourceClassMap.java is excluded by !sdk/**
  • sdk/src/main/java/org/zstack/sdk/ChangeHaNetworkGroupStateAction.java is excluded by !sdk/**
  • sdk/src/main/java/org/zstack/sdk/ChangeHaNetworkGroupStateResult.java is excluded by !sdk/**
  • sdk/src/main/java/org/zstack/sdk/CreateHaNetworkGroupAction.java is excluded by !sdk/**
  • sdk/src/main/java/org/zstack/sdk/CreateHaNetworkGroupResult.java is excluded by !sdk/**
  • sdk/src/main/java/org/zstack/sdk/DeleteHaNetworkGroupAction.java is excluded by !sdk/**
  • sdk/src/main/java/org/zstack/sdk/DeleteHaNetworkGroupResult.java is excluded by !sdk/**
  • sdk/src/main/java/org/zstack/sdk/HaNetworkGroupInventory.java is excluded by !sdk/**
  • sdk/src/main/java/org/zstack/sdk/QueryHaNetworkGroupAction.java is excluded by !sdk/**
  • sdk/src/main/java/org/zstack/sdk/QueryHaNetworkGroupResult.java is excluded by !sdk/**
  • sdk/src/main/java/org/zstack/sdk/UpdateHaNetworkGroupAction.java is excluded by !sdk/**
  • sdk/src/main/java/org/zstack/sdk/UpdateHaNetworkGroupResult.java is excluded by !sdk/**
📒 Files selected for processing (9)
  • conf/db/upgrade/V5.5.22__schema.sql
  • plugin/kvm/src/main/java/org/zstack/kvm/KVMAgentCommands.java
  • plugin/kvm/src/main/java/org/zstack/kvm/KVMConstant.java
  • simulator/simulatorImpl/src/main/java/org/zstack/simulator/kvm/KVMSimulatorConfig.java
  • simulator/simulatorImpl/src/main/java/org/zstack/simulator/kvm/KVMSimulatorController.java
  • testlib/src/main/java/org/zstack/testlib/ApiHelper.groovy
  • testlib/src/main/java/org/zstack/testlib/EnvSpec.groovy
  • testlib/src/main/java/org/zstack/testlib/KVMSimulator.groovy
  • utils/src/main/java/org/zstack/utils/clouderrorcode/CloudOperationsErrorCode.java

Comment on lines +8 to +9
`lastOpDate` TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP,
`createDate` TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00',
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 | 🔴 Critical | ⚡ Quick win

修复非法零时间默认值,避免升级脚本在严格模式下失败

Line 8、Line 9、Line 17、Line 18、Line 31、Line 32 使用了 DEFAULT '0000-00-00 00:00:00',这在 MySQL 8/GreatSQL 常见严格 SQL 模式下会导致 DDL 执行失败,属于升级阻断问题。

🛠️ 建议修复 diff
 CREATE TABLE IF NOT EXISTS `zstack`.`HaNetworkGroupVO` (
@@
-    `lastOpDate` TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP,
-    `createDate` TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00',
+    `lastOpDate` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+    `createDate` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
@@
 CREATE TABLE IF NOT EXISTS `zstack`.`HaNetworkGroupL3NetworkRefVO` (
@@
-    `lastOpDate` TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP,
-    `createDate` TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00',
+    `lastOpDate` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+    `createDate` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
@@
 CREATE TABLE IF NOT EXISTS `zstack`.`HostHaNetworkGroupStatusVO` (
@@
-    `lastOpDate` TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP,
-    `createDate` TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00',
+    `lastOpDate` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+    `createDate` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,

As per coding guidelines **/*.sql: Do not use DEFAULT 0000-00-00 00:00:00, use DEFAULT CURRENT_TIMESTAMP instead.

Also applies to: 17-18, 31-32

🤖 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 `@conf/db/upgrade/V5.5.22__schema.sql` around lines 8 - 9, Replace the invalid
zero-datetime defaults with CURRENT_TIMESTAMP: update the column definitions
that use `DEFAULT '0000-00-00 00:00:00'` (e.g., `lastOpDate`, `createDate` and
the other two occurrences) to use `DEFAULT CURRENT_TIMESTAMP` (and keep `ON
UPDATE CURRENT_TIMESTAMP` only on columns that should auto-update, e.g.,
`lastOpDate`), ensuring the NOT NULL semantics remain intact so the DDL will
succeed in strict SQL modes.

Comment on lines +1875 to +1918
public static final String ORG_ZSTACK_HA_10019 = "ORG_ZSTACK_HA_10019";

public static final String ORG_ZSTACK_HA_10020 = "ORG_ZSTACK_HA_10020";

public static final String ORG_ZSTACK_HA_10021 = "ORG_ZSTACK_HA_10021";

public static final String ORG_ZSTACK_HA_10022 = "ORG_ZSTACK_HA_10022";

public static final String ORG_ZSTACK_HA_10023 = "ORG_ZSTACK_HA_10023";

public static final String ORG_ZSTACK_HA_10024 = "ORG_ZSTACK_HA_10024";

public static final String ORG_ZSTACK_HA_10025 = "ORG_ZSTACK_HA_10025";

public static final String ORG_ZSTACK_HA_10026 = "ORG_ZSTACK_HA_10026";

public static final String ORG_ZSTACK_HA_10027 = "ORG_ZSTACK_HA_10027";

public static final String ORG_ZSTACK_HA_10028 = "ORG_ZSTACK_HA_10028";

public static final String ORG_ZSTACK_HA_10029 = "ORG_ZSTACK_HA_10029";

public static final String ORG_ZSTACK_HA_10030 = "ORG_ZSTACK_HA_10030";

public static final String ORG_ZSTACK_HA_10031 = "ORG_ZSTACK_HA_10031";

public static final String ORG_ZSTACK_HA_10032 = "ORG_ZSTACK_HA_10032";

public static final String ORG_ZSTACK_HA_10033 = "ORG_ZSTACK_HA_10033";

public static final String ORG_ZSTACK_HA_10034 = "ORG_ZSTACK_HA_10034";

public static final String ORG_ZSTACK_HA_10035 = "ORG_ZSTACK_HA_10035";

public static final String ORG_ZSTACK_HA_10036 = "ORG_ZSTACK_HA_10036";

public static final String ORG_ZSTACK_HA_10037 = "ORG_ZSTACK_HA_10037";

public static final String ORG_ZSTACK_HA_10038 = "ORG_ZSTACK_HA_10038";

public static final String ORG_ZSTACK_HA_10039 = "ORG_ZSTACK_HA_10039";

public static final String ORG_ZSTACK_HA_10040 = "ORG_ZSTACK_HA_10040";

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 | 🔴 Critical | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# 1. Check which of the new constants have message definitions in error-code resource files
echo "=== Searching for message definitions ==="
for code in $(seq 10019 10040); do
    key="ORG_ZSTACK_HA_${code}"
    count=$(rg -l "$key" --glob '*.properties' --glob '*.json' --glob '*.yaml' --glob '*.yml' 2>/dev/null | wc -l)
    echo "$key: $count file(s) with definition"
done

# 2. Check which of the new constants are referenced in Java/Groovy source code
echo ""
echo "=== Searching for usages in source code ==="
for code in $(seq 10019 10040); do
    key="ORG_ZSTACK_HA_${code}"
    count=$(rg -l "$key" --glob '*.java' --glob '*.groovy' 2>/dev/null | wc -l)
    echo "$key: $count file(s) referencing this constant"
done

Repository: MatheMatrix/zstack

Length of output: 252


🏁 Script executed:

#!/bin/bash
# Find error code message definitions and usages for ORG_ZSTACK_HA_10019-10040

echo "=== Searching for message definitions in properties/JSON/YAML files ==="
python3 << 'PYTHON_EOF'
import subprocess
import os

codes_without_defs = []
codes_with_defs = []

for code in range(10019, 10041):  # 10019 to 10040 inclusive
    key = f"ORG_ZSTACK_HA_{code}"
    result = subprocess.run(['rg', key, '-g', '*.properties', '-g', '*.json', '-g', '*.yaml', '-g', '*.yml'], 
                          capture_output=True, text=True)
    matches = result.stdout.strip()
    if matches:
        codes_with_defs.append((key, len(matches.split('\n'))))
    else:
        codes_without_defs.append(key)

if codes_with_defs:
    print(f"Codes WITH message definitions ({len(codes_with_defs)}):")
    for key, count in codes_with_defs:
        print(f"  {key}")
else:
    print("No message definitions found for any of the new codes")

if codes_without_defs:
    print(f"\nCodes WITHOUT message definitions ({len(codes_without_defs)}):")
    for key in codes_without_defs:
        print(f"  {key}")
PYTHON_EOF

echo ""
echo "=== Searching for usages in Java/Groovy source code ==="
python3 << 'PYTHON_EOF'
import subprocess

codes_with_usage = []
codes_without_usage = []

for code in range(10019, 10041):  # 10019 to 10040 inclusive
    key = f"ORG_ZSTACK_HA_{code}"
    result = subprocess.run(['rg', key, '-g', '*.java', '-g', '*.groovy'], 
                          capture_output=True, text=True)
    matches = result.stdout.strip()
    if matches:
        codes_with_usage.append((key, len(matches.split('\n'))))
    else:
        codes_without_usage.append(key)

if codes_with_usage:
    print(f"Codes WITH usages in source ({len(codes_with_usage)}):")
    for key, count in codes_with_usage[:10]:  # Show first 10
        print(f"  {key}: {count} match(es)")
    if len(codes_with_usage) > 10:
        print(f"  ... and {len(codes_with_usage) - 10} more")
else:
    print("No usages found for any of the new codes in source files")

if codes_without_usage:
    print(f"\nCodes NOT used in source ({len(codes_without_usage)}):")
    if len(codes_without_usage) <= 22:
        for key in codes_without_usage:
            print(f"  {key}")
PYTHON_EOF

# Also check the structure of error code message files
echo ""
echo "=== Finding error code message resource files ==="
find . -type f \( -name "*errorCode*" -o -name "*error*code*" \) \( -name "*.properties" -o -name "*.json" -o -name "*.yaml" -o -name "*.yml" \) | head -20

Repository: MatheMatrix/zstack

Length of output: 1394


新增的 22 个错误码缺少消息定义且未被使用

验证结果表明:

  • 所有 22 个新错误码(ORG_ZSTACK_HA_10019 ~ ORG_ZSTACK_HA_10040)均未在任何资源文件中定义消息
  • 所有 22 个新错误码在源代码中均没有被引用

这是一个关键问题:

  1. 错误码缺少对应的消息定义,运行时将无法获取到错误描述信息,影响用户体验
  2. 所有新增的错误码当前都是死代码,需要:
    • 补充消息定义(在 errorCode 相关资源文件中),且
    • 确保在实际业务代码中被引用使用

建议:如果这些错误码是预留性的,应在代码注释中明确说明其预期用途;否则应补充完整的定义和使用,或移除这些未使用的常量。

🤖 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 1875 - 1918, The new constants ORG_ZSTACK_HA_10019 through
ORG_ZSTACK_HA_10040 in CloudOperationsErrorCode are declared but lack message
definitions and are not referenced; either add message entries for each code in
the errorCode resource files and wire them into the ErrorCode/ResourceLoader
mechanism, then replace placeholder or create usage sites in business logic to
throw or return these codes (search for usages patterns like
ErrorCode/CLOUD_OPERATION_* or methods that create ErrorCode instances) or
remove the unused constants; if they are intended as reserved, add a clear
Javadoc comment on the constants explaining their planned purpose and why they
are unused.

@MatheMatrix MatheMatrix force-pushed the sync/haoyu.ding/fv-81413@@3 branch from db04ee4 to e09a677 Compare May 8, 2026 06:01
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 `@testlib/src/main/java/org/zstack/testlib/ApiHelper.groovy`:
- Around line 31804-31805: The queryHaNetworkGroup code calls
a.conditions.collect { it.toString() } unguarded and will NPE if a.conditions is
null; update the logic in queryHaNetworkGroup to null-safe the conversion by
first checking if a.conditions is null (or empty) and treating it as an empty
list before calling collect (e.g., replace the direct collect with a
null-coalescing or conditional that yields an empty list when a.conditions is
null), ensuring a.conditions is always a list of strings afterwards.
🪄 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: 5d141ce1-f4c2-4cf3-934c-c36e0943e533

📥 Commits

Reviewing files that changed from the base of the PR and between db04ee4 and e09a677.

⛔ Files ignored due to path filters (12)
  • sdk/src/main/java/SourceClassMap.java is excluded by !sdk/**
  • sdk/src/main/java/org/zstack/sdk/ChangeHaNetworkGroupStateAction.java is excluded by !sdk/**
  • sdk/src/main/java/org/zstack/sdk/ChangeHaNetworkGroupStateResult.java is excluded by !sdk/**
  • sdk/src/main/java/org/zstack/sdk/CreateHaNetworkGroupAction.java is excluded by !sdk/**
  • sdk/src/main/java/org/zstack/sdk/CreateHaNetworkGroupResult.java is excluded by !sdk/**
  • sdk/src/main/java/org/zstack/sdk/DeleteHaNetworkGroupAction.java is excluded by !sdk/**
  • sdk/src/main/java/org/zstack/sdk/DeleteHaNetworkGroupResult.java is excluded by !sdk/**
  • sdk/src/main/java/org/zstack/sdk/HaNetworkGroupInventory.java is excluded by !sdk/**
  • sdk/src/main/java/org/zstack/sdk/QueryHaNetworkGroupAction.java is excluded by !sdk/**
  • sdk/src/main/java/org/zstack/sdk/QueryHaNetworkGroupResult.java is excluded by !sdk/**
  • sdk/src/main/java/org/zstack/sdk/UpdateHaNetworkGroupAction.java is excluded by !sdk/**
  • sdk/src/main/java/org/zstack/sdk/UpdateHaNetworkGroupResult.java is excluded by !sdk/**
📒 Files selected for processing (9)
  • conf/db/upgrade/V5.5.22__schema.sql
  • plugin/kvm/src/main/java/org/zstack/kvm/KVMAgentCommands.java
  • plugin/kvm/src/main/java/org/zstack/kvm/KVMConstant.java
  • simulator/simulatorImpl/src/main/java/org/zstack/simulator/kvm/KVMSimulatorConfig.java
  • simulator/simulatorImpl/src/main/java/org/zstack/simulator/kvm/KVMSimulatorController.java
  • testlib/src/main/java/org/zstack/testlib/ApiHelper.groovy
  • testlib/src/main/java/org/zstack/testlib/EnvSpec.groovy
  • testlib/src/main/java/org/zstack/testlib/KVMSimulator.groovy
  • utils/src/main/java/org/zstack/utils/clouderrorcode/CloudOperationsErrorCode.java
✅ Files skipped from review due to trivial changes (3)
  • testlib/src/main/java/org/zstack/testlib/EnvSpec.groovy
  • plugin/kvm/src/main/java/org/zstack/kvm/KVMConstant.java
  • utils/src/main/java/org/zstack/utils/clouderrorcode/CloudOperationsErrorCode.java
🚧 Files skipped from review as they are similar to previous changes (2)
  • testlib/src/main/java/org/zstack/testlib/KVMSimulator.groovy
  • simulator/simulatorImpl/src/main/java/org/zstack/simulator/kvm/KVMSimulatorController.java

Comment on lines +31804 to +31805
a.conditions = a.conditions.collect { it.toString() }

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 | ⚡ Quick win

queryHaNetworkGroup 在无查询条件时可能抛出 NPE

Line 31804 直接对 a.conditions 调用 collect,当调用方未设置 conditions 时会在运行时失败,导致查询接口不可用。

建议修复
-        a.conditions = a.conditions.collect { it.toString() }
+        a.conditions = a.conditions?.collect { it?.toString() } ?: []
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
a.conditions = a.conditions.collect { it.toString() }
a.conditions = a.conditions?.collect { it?.toString() } ?: []
🤖 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 `@testlib/src/main/java/org/zstack/testlib/ApiHelper.groovy` around lines 31804
- 31805, The queryHaNetworkGroup code calls a.conditions.collect { it.toString()
} unguarded and will NPE if a.conditions is null; update the logic in
queryHaNetworkGroup to null-safe the conversion by first checking if
a.conditions is null (or empty) and treating it as an empty list before calling
collect (e.g., replace the direct collect with a null-coalescing or conditional
that yields an empty list when a.conditions is null), ensuring a.conditions is
always a list of strings afterwards.

@zstack-robot-2
Copy link
Copy Markdown
Collaborator

Comment from yaohua.wu:

Review: MR !9779 — ZSTAC-81413(Network Group HA — zstack 基础层)

评审范围:21 文件,主要为 V5.5.22__schema.sql 新增 4 张表、KVMConstant 三个新路径、KVMAgentCommands 两个新命令 + StartVmCmd.enableHa 字段、自动生成 SDK / ApiHelper、22 个新增 ORG_ZSTACK_HA_xxxx 错误码、EnvSpec 白名单、KVMSimulatorConfig/Controller/KVMSimulator 仿真对接。

关联 MR

  • premium !13766:HA 网络组主体业务(API handler、HaManagerImplHaVmLifecycleExtensionHaNetworkGroupHostAllocatorFilterHaNetworkGroupRiskHelper、zwatch 告警与测试用例),消费本 MR 中的 KVMConstant.HA_NETWORK_GROUP_SYNC_PATH 与新错误码。
  • zstack-utility !7017:KVM agent 侧 host_plugin.py / vm_plugin.py 实现 enableHa 元数据 live 写入与重置;ha_plugin.py diff 为空(见跨仓评审)。

🔴 Critical

1. KVMConstant.HA_NETWORK_GROUP_SYNC_PATH 在 agent 侧没有 handler

  • 本 MR 新增常量:
    String HA_NETWORK_GROUP_SYNC_PATH = "/ha/networkgroup/sync";
    premium MR 通过 HaNetworkGroupCommands / HaManagerImplSyncHaNetworkGroupConfigCmd 发到此路径,仿真器在 KVMSimulatorController.syncHaNetworkGroupConfig 里收下;但 zstack-utility !7017 的 kvmagent/plugins/ha_plugin.py base→head diff 为空,真实环境主机没注册该 URI,会 404。
  • 修复:在 zstack-utility 补 ha_plugin.pyregister_async_uri('/ha/networkgroup/sync', ...) 与对应 monitor 处理逻辑;并补齐 host→MN 的 /ha/networkgroup/report 上行通路。

2. HaNetworkGroupGlobalConfigVersionVO 没有 schema 级单调约束 / 起始值仅 0

  • V5.5.22__schema.sql
    CREATE TABLE IF NOT EXISTS `HaNetworkGroupGlobalConfigVersionVO` (
        `name` VARCHAR(64) NOT NULL,
        `version` BIGINT UNSIGNED NOT NULL DEFAULT 0,
        PRIMARY KEY (`name`)
    );
    INSERT IGNORE INTO `HaNetworkGroupGlobalConfigVersionVO` (`name`,`version`) VALUES ('ha-network-group', 0);
  • 仅靠应用层做 version = version + 1 时,并发的 Update/Delete/ChangeState/AttachNic 各自读到旧 version → 都把它写为 old+1,会出现版本号回退或漏号。需要确认 premium 侧 HaManagerImpl 自增是用 UPDATE … SET version=version+1 WHERE name=?(原子 SQL)而非「读后写」。schema 上无法强约束,但可以加 CHECK (version >= 0) + 文档约束(MySQL 5.7 之前不强校验,纯说明性)。
  • 修复:要么 schema 加注释,要么在 premium 侧确保使用单条 UPDATE 原子自增。

🟡 Warning

3. 22 个新增错误码 ORG_ZSTACK_HA_10019..10040 是否全部被引用?

  • utils/.../CloudOperationsErrorCode.java 一次性新增 22 个常量(10019–10040)。premium 侧本 MR 当前可见 diff 中我只观察到 ORG_ZSTACK_HA_10031 / _10032 的引用(HaVmLevelSubManager),其余靠 HaManagerImpl 兜底。
  • 修复:合并前在 premium 仓库 grep -rn ORG_ZSTACK_HA_100[2-4] 一次,把孤儿错误码删除或补引用,并确认 errorCode.properties 已新增对应 i18n 文案。

4. HaNetworkGroupL3NetworkRefVO 唯一索引覆盖范围

  • UNIQUE INDEX ukHaNetworkGroupL3NetworkRefVOl3NetworkUuid (l3NetworkUuid) 强约束「一个 L3 至多在一个组」,与 PRD 一致。
  • 但缺乏 (haNetworkGroupUuid, l3NetworkUuid) 组合唯一索引;并发 UpdateHaNetworkGroup 走「先 delete 旧 ref 再 insert 新 ref」时,同一 (group, l3) 可能出现两条记录的极短窗口。建议追加:
    UNIQUE INDEX ukHaNetworkGroupL3NetworkRefVOgroupL3 (haNetworkGroupUuid, l3NetworkUuid)

5. HostHaNetworkGroupStatusVO.status 的取值约束不在 schema 层

  • status VARCHAR(32) NOT NULL DEFAULT 'Unknown' 但允许任意 32 字节字符串。premium 侧定义为枚举 Available/Degrade/Down/Unknown,可考虑在 SQL 里加 CHECK status IN (…)(虽然 MySQL 5.7 不强制,但 8.0+ 强制);至少在 schema 注释里写明可选值,便于 DBA 排障。

6. KVMAgentCommands.StartVmCmd.enableHa 仍是 @GrayVersion("5.5.6")

  • 历史灰度起点是 5.5.6,本 MR 目标 5.5.22。若集群从 < 5.5.6 升级到 5.5.22,enableHa 字段会被旧 agent 解析失败 — gray-upgrade 框架已经会处理这点,OK。
  • 但请同步检查 conf/grayUpgrade/grayUpgrade.json(在 premium MR 里)是否对 SetupVmHaEnabledMetadataLiveCmd / ReconcileVmHaEnabledMetadataLiveCmd 也作了登记(premium 评审里看到登记了)。

7. EnvSpec.groovy 白名单加入 HaNetworkGroupGlobalConfigVersionVO

  • 这一个 VO 是单行配置版本表,留底是合理的;但其他 3 张新表(HaNetworkGroupVO/L3NetworkRefVO/HostHaNetworkGroupStatusVO)是否需要在 EnvSpec.cleanupTables 里显式列出?默认 zstack 集成测试会按表清空,但 case 之间的 setEnv 重置语义需作者确认。

🟢 Suggestion

  • 仿真器 KVMSimulatorController.syncHaNetworkGroupConfig 把请求体当作 String 入栈:
    config.syncHaNetworkGroupConfigCmds.add(entity.getBody());
    其他 simulator 都解析为强类型 cmd 对象。建议解析为 SyncHaNetworkGroupConfigCmd(类型在 premium 里),便于 case 写断言。
  • 错误码常量集中加在 CloudOperationsErrorCode.java 末尾,OK,但要保证对应 errorCode.properties(中英)同步更新——本 MR 看不到 properties 改动。
  • KVMConstant.UPDATE_VM_CONSOLE_PASSWORD_PATH 与新增的 SETUP_VM_HA_ENABLED_METADATA_LIVE_PATH 都用 /host/vm/... 前缀,规则一致;建议团队后续在 KVMConstant 里把 host live-update 类常量集中归类。
  • HaNetworkGroupVO schema 把 state 默认值写死 'Enabled',与 premium VO 的枚举语义一致;将来若引入 Disabled 之外的第三态,需要双侧同步。

跨仓一致性

  • 路径常量、cmd 字段、StartVmCmd 字段三个跨仓接口一致;唯一阻塞点是 zstack-utility !7017 的 ha_plugin.py 实际无变更,导致 HA_NETWORK_GROUP_SYNC_PATH 在生产环境无 handler。

Verdict: REVISION_REQUIRED

阻塞项:①HA_NETWORK_GROUP_SYNC_PATH 配套 agent 端缺实现;②HaNetworkGroupGlobalConfigVersionVO 自增需要在 premium HaManagerImpl 用单 SQL 原子完成(请提供证据)。Warning 级条目建议在合并前 sweep 一遍。


🤖 Robot Reviewer

@MatheMatrix MatheMatrix force-pushed the sync/haoyu.ding/fv-81413@@3 branch from e09a677 to 3734fad Compare May 9, 2026 04:08
DBImpact

Resolves: ZSTAC-81413

Change-Id: I6a7574656467636e686377756f716d67707a7063
@MatheMatrix MatheMatrix force-pushed the sync/haoyu.ding/fv-81413@@3 branch from 3734fad to 96fe476 Compare May 9, 2026 08:00
@zstack-robot-2
Copy link
Copy Markdown
Collaborator

Comment from gitlab:

自上次添加REVIEWED标签(2026-05-09 13:48:10.000Z)后, 有新的COMMIT更新(2026-05-09 16:00:06.408Z), 所以移除了REVIEWED标签

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.

3 participants