-
Notifications
You must be signed in to change notification settings - Fork 0
<fix>[sdnController]: set lacp mode when change host #3145
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: 5.5.0
Are you sure you want to change the base?
Conversation
工作流总结强化 APISdnControllerChangeHostMsg 的校验与控制流:要求显式指定 BondMode、校验 NIC 名称非空,单 NIC 情况提前清除并返回,调整多 NIC 时 BondMode 与 LacpMode 的继承与强制规则;Vtep/Netmask 与 NIC 名称解析保持不变。 (≤50 字) 变更详情
Sequence Diagram(s)(不生成序列图;变更为单个拦截器内的验证与控制流调整,且交互组件少,故省略。) 代码审查工作量评估🎯 2 (简单) | ⏱️ ~12 分钟 诗
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
📜 Recent review detailsConfiguration used: Path: http://open.zstack.ai:20001/code-reviews/zstack-cloud.yaml (via .coderabbit.yaml) Review profile: CHILL Plan: Pro 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
Comment |
Resolves: ZSTAC-76537 Change-Id: I61636a6e78746b7166796572677a7a746c6d7469 Signed-off-by: zhangjianjun <jianjun.zhang@zstack.io>
4cbc8b1 to
ae8bd9c
Compare
There was a problem hiding this 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
📜 Review details
Configuration used: Path: http://open.zstack.ai:20001/code-reviews/zstack-cloud.yaml (via .coderabbit.yaml)
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
plugin/sdnController/src/main/java/org/zstack/sdnController/SdnControllerApiInterceptor.java
🧰 Additional context used
📓 Path-based instructions (3)
**/*.*
⚙️ CodeRabbit configuration file
**/*.*: - 代码里不应当有有中文,包括报错、注释等都应当使用正确的、无拼写错误的英文来写
Files:
plugin/sdnController/src/main/java/org/zstack/sdnController/SdnControllerApiInterceptor.java
**/*Interceptor.java
⚙️ CodeRabbit configuration file
**/*Interceptor.java: - 注意检查来自 Message 的参数是否做过 trim,用户可能在浏览器上复制粘贴的数据带有空格、换行符等
Files:
plugin/sdnController/src/main/java/org/zstack/sdnController/SdnControllerApiInterceptor.java
**/*.java
⚙️ CodeRabbit configuration file
**/*.java: ## 1. API 设计要求
- API 命名:
- API 名称必须唯一,不能重复。
- API 消息类需要继承
APIMessage;其返回类必须继承APIReply或APIEvent,并在注释中用@RestResponse进行标注。- API 消息上必须添加注解
@RestRequest,并满足如下规范:
path:
- 针对资源使用复数形式。
- 当 path 中引用消息类变量时,使用
{variableName}格式。- HTTP 方法对应:
- 查询操作 →
HttpMethod.GET- 更新操作 →
HttpMethod.PUT- 创建操作 →
HttpMethod.POST- 删除操作 →
HttpMethod.DELETE- API 类需要实现
__example__方法以便生成 API 文档,并确保生成对应的 Groovy API Template 与 API Markdown 文件。
2. 命名与格式规范
类名:
- 使用 UpperCamelCase 风格。
- 特殊情况:
- VO/AO/EO 类型类除外。
- 抽象类采用
Abstract或Base前缀/后缀。- 异常类应以
Exception结尾。- 测试类需要以
Test或Case结尾。方法名、参数名、成员变量和局部变量:
- 使用 lowerCamelCase 风格。
常量命名:
- 全部大写,使用下划线分隔单词。
- 要求表达清楚,避免使用含糊或不准确的名称。
包名:
- 统一使用小写,使用点分隔符,每个部分应是一个具有自然语义的英文单词(参考 Spring 框架的结构)。
命名细节:
- 避免在父子类或同一代码块中出现相同名字的成员或局部变量,防止混淆。
- 命名缩写:
- 不允许使用不必要的缩写,如:
AbsSchedulerJob、condi、Fu等。应使用完整单词提升可读性。
3. 编写自解释代码
意图表达:
- 避免使用布尔型参数造成含义不明确。例如:
- 对于
stopAgent(boolean ignoreError),建议拆分为不同函数(如stopAgentIgnoreError()),或使用枚举表达操作类型。- 命名应尽量用完整的单词组合表达意图,并在名称中体现数据类型或用途(例如在常量与变量名称中,将类型词放在末尾)。
- 避免使用魔法值(Magic Value):
直接使用未经定义的数值或字符串(如 if (status == 5))应替换为枚举或常量。
示例:
// 错误示例:魔法值
if (user.getStatus() == 5) { ... }
// 正确示例:常量或枚举
public static final int STATUS_ACTIVE = 5;
if (user.getStatus() == STATUS_ACTIVE) { ... }
// 或使用枚举
enum UserStatus { ACTIVE, INACTIVE }
注释:
- 代码应尽量做到自解释,对少于两行的说明可以直接写在代码中。
- 对于较长的注释,需要仔细校对并随代码更新,确保内容正确。
- 接口方法不应有多余的修饰符(例如
public),且必须配有有效的 Javadoc 注释。
4. 流程控制和结构优化
if...else 的使用:
- 应尽量减少 if...else 结构的使用,建议:
- 限制嵌套层级最多为两层,且内层不应再出现
else分支。- 尽早返回(Early Return),将条件判断中的处理逻辑提前结束或抽成独立方法。
- 使用 Java Stream 或 Lambda 表达式代替冗长的循环与条件判断。
条件判断:
- if 条件表达不宜过长或过于复杂,必要时可以将条件抽成 boolean 变量描述。
代码块长度:
...
Files:
plugin/sdnController/src/main/java/org/zstack/sdnController/SdnControllerApiInterceptor.java
🧠 Learnings (2)
📚 Learning: 2025-08-10T13:42:01.027Z
Learnt from: MatheMatrix
Repo: MatheMatrix/zstack PR: 2410
File: compute/src/main/java/org/zstack/compute/vm/VmInstanceHelper.java:334-356
Timestamp: 2025-08-10T13:42:01.027Z
Learning: 在 ZStack 的 `VmInstanceHelper.validateVmNicParams` 方法中调用 `VmNicParamValidator` 时,不需要对 msg.getType() 返回 null 的情况进行兼容处理,因为 vmType 为 null 的情况已在内部(VmNicParamValidator 或其他地方)得到处理。
Applied to files:
plugin/sdnController/src/main/java/org/zstack/sdnController/SdnControllerApiInterceptor.java
📚 Learning: 2025-10-28T02:29:38.803Z
Learnt from: MatheMatrix
Repo: MatheMatrix/zstack PR: 2823
File: plugin/kvm/src/main/java/org/zstack/kvm/KVMHost.java:786-831
Timestamp: 2025-10-28T02:29:38.803Z
Learning: APIUpdateHostnameMsg 的主机名有效性已在 API 层(HostApiInterceptor/VmHostnameUtils)完成校验;KVMHost.handle(UpdateHostnameMsg) 不应重复校验。
Applied to files:
plugin/sdnController/src/main/java/org/zstack/sdnController/SdnControllerApiInterceptor.java
🔇 Additional comments (5)
plugin/sdnController/src/main/java/org/zstack/sdnController/SdnControllerApiInterceptor.java (5)
209-212: 验证逻辑正确。添加的空网卡名称验证是合理的,可以防止无效操作。
214-218: 单网卡逻辑正确。当只有一个网卡时清除 bond 和 lacp 模式并提前返回的逻辑是正确的,因为绑定至少需要两个网卡。
183-233: 此代码不需要额外的 trim 处理。根据 ZStack 框架设计,APISdnControllerChangeHostMsg 继承自 APIMessage,框架在 validate() 方法中会自动对所有字符串类型的 API 参数进行 trim 处理,除非在 @APIParam 注解中明确设置
noTrim = true。本代码中所有字符串参数(bondMode、lacpMode、vtepIp、netmask 等)都未设置noTrim = true,因此框架已在消息验证阶段自动完成 trim 操作。拦截器中直接使用这些参数值是正确的,无需手动再次 trim。
10-10: 删除未使用的SQL导入。
SQL类在该文件中未被使用,建议删除第 10 行的导入以保持代码整洁。⛔ Skipped due to learnings
Learnt from: MatheMatrix Repo: MatheMatrix/zstack PR: 2199 File: plugin/securityGroup/src/main/java/org/zstack/network/securitygroup/SecurityGroupApiInterceptor.java:745-745 Timestamp: 2025-06-19T10:34:39.243Z Learning: SecurityGroupApiInterceptor.java 中需要对以下类型的外部字符串参数进行 trim 处理:1) IP相关字段(getAllowedCidr, getSrcIpRange, getDstIpRange) 2) 端口字段(getDstPortRange) 3) UUID字段(getRemoteSecurityGroupUuid等) 4) 描述字段(getDescription) 5) 枚举字符串字段(getProtocol, getAction, getState, getType)。这些参数在进入 validateIps, validatePorts 以及所有 validate 方法之前都应当被 trim,以防止空格、换行符等不可见字符影响验证逻辑。Learnt from: zstack-robot-2 Repo: MatheMatrix/zstack PR: 2360 File: compute/src/main/java/org/zstack/compute/vm/VmAllocateNicIpFlow.java:75-98 Timestamp: 2025-08-04T03:21:42.427Z Learning: 在 VmAllocateNicIpFlow.java 中,团队认为复杂的 appliance VM IP 分配逻辑(第79-96行)属于约定俗成的代码模式,不需要额外的详细注释。第96行的注释已经被认为是充分的。Learnt from: MatheMatrix Repo: MatheMatrix/zstack PR: 2199 File: plugin/securityGroup/src/main/java/org/zstack/network/securitygroup/SecurityGroupApiInterceptor.java:745-745 Timestamp: 2025-06-19T10:34:39.243Z Learning: 在 SecurityGroupApiInterceptor.java 中,所有来自 API Message 的外部字符串参数(如 IP 范围、端口范围、安全组 UUID、描述等)都应当在 validate 方法中进行 trim 处理,以防止用户在浏览器中复制粘贴带有空格、换行符、回车符等不可见字符的数据影响验证逻辑。Learnt from: zstack-robot-1 Repo: MatheMatrix/zstack PR: 2418 File: compute/src/main/java/org/zstack/compute/vm/VmInstanceApiInterceptor.java:571-576 Timestamp: 2025-08-12T06:22:50.614Z Learning: 在 ZStack 的 VmInstanceApiInterceptor 中,IPv6 前缀的验证分为两层:1) API 拦截器层面仅处理格式验证(字符串转整数),避免格式错误;2) 实际的业务逻辑验证(如范围检查 [0, 128])在 ipOperator.validateStaticIp() 方法中进行。这是一种关注点分离的设计模式。Learnt from: MatheMatrix Repo: MatheMatrix/zstack PR: 2410 File: compute/src/main/java/org/zstack/compute/vm/VmInstanceHelper.java:334-356 Timestamp: 2025-08-10T13:42:01.027Z Learning: 在 ZStack 的 `VmInstanceHelper.validateVmNicParams` 方法中调用 `VmNicParamValidator` 时,不需要对 msg.getType() 返回 null 的情况进行兼容处理,因为 vmType 为 null 的情况已在内部(VmNicParamValidator 或其他地方)得到处理。Learnt from: zstack-robot-1 Repo: MatheMatrix/zstack PR: 2418 File: compute/src/main/java/org/zstack/compute/vm/VmInstanceApiInterceptor.java:571-576 Timestamp: 2025-08-12T06:22:50.614Z Learning: 在 ZStack 的 VmInstanceApiInterceptor 中,IPv6 前缀的验证分为两层:1) API 拦截器层面仅处理格式验证(字符串转整数),避免格式错误;2) 实际的业务逻辑验证(如范围检查 [0, 128])在 StaticIpOperator.validateStaticIp() 方法中进行。这是一种关注点分离的设计模式。Learnt from: zstack-robot-2 Repo: MatheMatrix/zstack PR: 2435 File: storage/src/main/java/org/zstack/storage/snapshot/group/VolumeSnapshotGroupBase.java:47-47 Timestamp: 2025-08-14T06:56:19.585Z Learning: 在VolumeSnapshotGroupBase.java中,VmInstanceResourceMetadataManager的注入和SKIP_RESOURCE_ROLLBACK标记虽然在当前版本中未被使用,但这些导入在大型重构PR中是有意为之的,用于保持代码一致性或为后续功能做准备。Learnt from: zstack-robot-2 Repo: MatheMatrix/zstack PR: 2250 File: network/src/main/java/org/zstack/network/l3/L3NetworkApiInterceptor.java:133-139 Timestamp: 2025-07-07T07:03:01.181Z Learning: 在 L3NetworkApiInterceptor.java 中处理 IP 地址参数时,不需要进行 trim 处理,因为 NetworkUtils.isValidIPAddress() 方法本身就会拒绝包含空格、换行符等不符合 IP 格式的字符串,IP 地址验证已经足够严格来捕获这些格式错误。Learnt from: MatheMatrix Repo: MatheMatrix/zstack PR: 2763 File: sdk/src/main/java/org/zstack/sdk/UpdateHostKernelInterfaceAction.java:31-31 Timestamp: 2025-10-20T11:27:25.928Z Learning: UpdateHostKernelInterface API (`sdk/src/main/java/org/zstack/sdk/UpdateHostKernelInterfaceAction.java`) 在 PR #2763 时尚未被实际使用,因此对其参数约束的变更(如 name 字段从必需改为可选)不会造成破坏性影响。Learnt from: ZStack-Robot Repo: MatheMatrix/zstack PR: 2418 File: compute/src/main/java/org/zstack/compute/vm/VmInstanceBase.java:3856-3865 Timestamp: 2025-08-12T05:39:14.846Z Learning: 在 compute/src/main/java/org/zstack/compute/vm/VmInstanceBase.java 的 setNoIpAllocationStaticIp 流程中,从数据库加载的 VmNicVO 实例其 getUsedIps() 为空时也不会为 null(返回空集合)。因此无需对 getUsedIps() 再做 Optional/空列表归一化的空指针保护;若找不到对应 NIC,使用 orElse(new VmNicVO()) 的约定允许后续逻辑通过 NPE 暴露问题,与项目既有约定一致。
204-207: 此注释不成立。APISdnControllerChangeHostMsg是在此提交中新增的 API,不是对现有行为的修改。该 API 之前不存在,因此没有现有的调用方会因此受到影响。在
APISdnControllerAddHostMsg中默认 bondMode(用于新增主机)与在APISdnControllerChangeHostMsg中要求指定 bondMode(用于修改主机)是不同的设计意图,这是合理的:新增操作可以使用默认值,而修改操作需要显式指定以避免意外改动。Likely an incorrect or invalid review comment.
| if (msg.getBondMode().equals(refVO.getBondMode())) { | ||
| msg.setLacpMode(refVO.getLacpMode()); | ||
| } | ||
|
|
||
| if (msg.getBondMode() != null && msg.getBondMode().equals(L2NetworkConstant.BONDING_MODE_TCP) && msg.getLacpMode() == null) { | ||
| if (msg.getBondMode().equals(L2NetworkConstant.BONDING_MODE_TCP)) { | ||
| msg.setLacpMode(L2NetworkConstant.LACP_MODE_ACTIVE); | ||
| } else if (msg.getBondMode().equals(L2NetworkConstant.BONDING_MODE_SLB)) { | ||
| if (!(msg.getLacpMode().equals(L2NetworkConstant.LACP_MODE_PASSIVE) || msg.getLacpMode().equals(L2NetworkConstant.LACP_MODE_OFF))) { | ||
| msg.setLacpMode(L2NetworkConstant.LACP_MODE_OFF); | ||
| } | ||
| } else { | ||
| msg.setLacpMode(L2NetworkConstant.LACP_MODE_OFF); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
修复关键的逻辑错误和潜在的空指针异常。
存在两个严重问题:
-
逻辑错误:第 220-222 行的 if 语句保存了 refVO 的 lacpMode,但后续第 224-232 行的 if 语句会无条件执行并覆盖该值。这导致第 221 行的设置完全失效。
-
潜在的 NPE:第 227 行在 bondMode 为 SLB 时调用
msg.getLacpMode().equals(),如果msg.getLacpMode()为 null 会抛出空指针异常。
🔎 建议的修复方案
if (msg.getBondMode().equals(refVO.getBondMode())) {
msg.setLacpMode(refVO.getLacpMode());
-}
-
-if (msg.getBondMode().equals(L2NetworkConstant.BONDING_MODE_TCP)) {
+} else if (msg.getBondMode().equals(L2NetworkConstant.BONDING_MODE_TCP)) {
msg.setLacpMode(L2NetworkConstant.LACP_MODE_ACTIVE);
} else if (msg.getBondMode().equals(L2NetworkConstant.BONDING_MODE_SLB)) {
- if (!(msg.getLacpMode().equals(L2NetworkConstant.LACP_MODE_PASSIVE) || msg.getLacpMode().equals(L2NetworkConstant.LACP_MODE_OFF))) {
+ if (msg.getLacpMode() == null ||
+ !(msg.getLacpMode().equals(L2NetworkConstant.LACP_MODE_PASSIVE) || msg.getLacpMode().equals(L2NetworkConstant.LACP_MODE_OFF))) {
msg.setLacpMode(L2NetworkConstant.LACP_MODE_OFF);
}
} else {
msg.setLacpMode(L2NetworkConstant.LACP_MODE_OFF);
}🤖 Prompt for AI Agents
In
plugin/sdnController/src/main/java/org/zstack/sdnController/SdnControllerApiInterceptor.java
around lines 220-232, the code currently sets msg.lacpMode from refVO then
unconditionally overwrites it and calls equals on possibly-null values; change
the logic to (1) use null-safe comparisons (e.g. Objects.equals or
constant.equals(var)) everywhere to avoid NPEs, (2) only apply the refVO
lacpMode when the incoming msg.lacpMode is null or when bondMode differs (so it
isn't immediately overwritten), and (3) when applying bond-mode defaults, only
set lacpMode if it is still null or not explicitly provided; update the
conditional order/guards accordingly so refVO values are preserved when intended
and no equals() is called on a null string.
Resolves: ZSTAC-76537
Change-Id: I61636a6e78746b7166796572677a7a746c6d7469
Signed-off-by: zhangjianjun jianjun.zhang@zstack.io
sync from gitlab !8959