-
Notifications
You must be signed in to change notification settings - Fork 0
<fix>[ceph]: support thirdparty_ceph to bm root volume #3189
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.6
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,4 +2,79 @@ ALTER TABLE `GuestVmScriptExecutedRecordDetailVO` | |
| MODIFY `stdout` MEDIUMTEXT CHARACTER SET `utf8mb4` COLLATE `utf8mb4_unicode_ci`; | ||
|
|
||
| ALTER TABLE `GuestVmScriptExecutedRecordDetailVO` | ||
| MODIFY `stderr` MEDIUMTEXT CHARACTER SET `utf8mb4` COLLATE `utf8mb4_unicode_ci`; | ||
| MODIFY `stderr` MEDIUMTEXT CHARACTER SET `utf8mb4` COLLATE `utf8mb4_unicode_ci`; | ||
|
|
||
| DELIMITER $$ | ||
|
|
||
| CREATE PROCEDURE UpdateBareMetal2InstanceProvisionNicVO() | ||
| BEGIN | ||
| DECLARE instanceUuid_exists INT; | ||
| DECLARE isPrimaryProvisionNic_exists_in_ProvisionNicVO INT; | ||
| DECLARE isPrimaryProvisionNic_exists_in_ChassisNicVO INT; | ||
|
|
||
| DECLARE EXIT HANDLER FOR SQLEXCEPTION | ||
| BEGIN | ||
| ROLLBACK; | ||
| SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'An error occurred during the update process.'; | ||
| END; | ||
|
|
||
| START TRANSACTION; | ||
|
|
||
| SELECT COUNT(*) | ||
| INTO instanceUuid_exists | ||
| FROM INFORMATION_SCHEMA.COLUMNS | ||
| WHERE TABLE_SCHEMA = 'zstack' | ||
| AND TABLE_NAME = 'BareMetal2InstanceProvisionNicVO' | ||
| AND COLUMN_NAME = 'instanceUuid'; | ||
|
|
||
| IF instanceUuid_exists = 0 THEN | ||
| CALL ADD_COLUMN('BareMetal2InstanceProvisionNicVO', 'instanceUuid', 'VARCHAR(32)', FALSE, ''); | ||
|
|
||
| UPDATE `zstack`.`BareMetal2InstanceProvisionNicVO` | ||
| SET `instanceUuid` = `uuid`; | ||
|
|
||
| ALTER TABLE `zstack`.`BareMetal2InstanceProvisionNicVO` | ||
| DROP FOREIGN KEY `fkBareMetal2InstanceProvisionNicVOInstanceVO`; | ||
|
|
||
| CALL ADD_CONSTRAINT('BareMetal2InstanceProvisionNicVO', 'fkBareMetal2InstanceProvisionNicVOInstanceVO', | ||
| 'instanceUuid', 'BareMetal2InstanceVO', 'uuid', 'CASCADE'); | ||
|
Comment on lines
+36
to
+40
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 外键删除操作缺少存在性检查,影响脚本幂等性
建议在删除外键前先检查其是否存在,类似于列的存在性检查方式: 🔧 建议的修复方案+ -- Check if foreign key exists before dropping
+ SELECT COUNT(*)
+ INTO @fk_exists
+ FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS
+ WHERE TABLE_SCHEMA = 'zstack'
+ AND TABLE_NAME = 'BareMetal2InstanceProvisionNicVO'
+ AND CONSTRAINT_NAME = 'fkBareMetal2InstanceProvisionNicVOInstanceVO'
+ AND CONSTRAINT_TYPE = 'FOREIGN KEY';
+
+ IF @fk_exists > 0 THEN
ALTER TABLE `zstack`.`BareMetal2InstanceProvisionNicVO`
DROP FOREIGN KEY `fkBareMetal2InstanceProvisionNicVOInstanceVO`;
+ END IF;Based on learnings,ZStack 升级脚本需要通过 information_schema 检查表和约束的存在性来确保脚本可以安全重复执行。 🤖 Prompt for AI Agents |
||
|
|
||
| UPDATE `zstack`.`BareMetal2InstanceProvisionNicVO` | ||
| SET `uuid` = REPLACE(UUID(), '-', ''); | ||
|
Comment on lines
+42
to
+43
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
# 搜索 Java 代码中是否有其他表引用 BareMetal2InstanceProvisionNicVO.uuid
# 查找 BareMetal2InstanceProvisionNicVO 相关的引用
rg -n "BareMetal2InstanceProvisionNicVO" --type java -C 3
# 搜索 SQL schema 中的外键定义
rg -n "BareMetal2InstanceProvisionNic" --glob "*.sql" -C 3
# 查找 VO 定义文件
fd "BareMetal2InstanceProvisionNicVO.java" --type fRepository: MatheMatrix/zstack Length of output: 6310 🏁 Script executed: # 查看升级脚本的完整上下文
head -50 conf/db/upgrade/V5.5.6__schema.sql
tail -20 conf/db/upgrade/V5.5.6__schema.sql
wc -l conf/db/upgrade/V5.5.6__schema.sqlRepository: MatheMatrix/zstack Length of output: 2669 🏁 Script executed: # 检查是否有外键约束引用此表的 uuid
rg -n "FOREIGN KEY" conf/db/upgrade/V5.5.6__schema.sql -C 3Repository: MatheMatrix/zstack Length of output: 466 🏁 Script executed: # 搜索所有引用 BareMetal2InstanceProvisionNicVO.uuid 的外键约束
rg -n "BareMetal2InstanceProvisionNicVO" conf/db/upgrade/ --glob "*.sql" -B 2 -A 2 | rg -i "foreign|constraint|reference"
# 具体查看 BareMetal2BondingNicRefVO 相关的处理
rg -n "BareMetal2BondingNicRefVO" conf/db/upgrade/ --glob "*.sql" -C 3
# 检查 V5.5.6 脚本中是否处理了 provisionNicUuid
grep -n "provisionNicUuid\|BondingNicRefVO" conf/db/upgrade/V5.5.6__schema.sqlRepository: MatheMatrix/zstack Length of output: 2286 🏁 Script executed: # 查看完整的 V4.7.13 脚本中关于 BondingNicRefVO 的处理
cat conf/db/upgrade/V4.7.13__schema.sql | grep -n "BondingNicRefVO" -A 3 -B 3Repository: MatheMatrix/zstack Length of output: 611 🏁 Script executed: # 检查 upgrade 脚本中是否有对 provisionNicUuid 的更新操作
rg -n "provisionNicUuid" conf/db/upgrade/ --glob "*.sql"Repository: MatheMatrix/zstack Length of output: 399 🏁 Script executed: # 查看 ADD_CONSTRAINT 函数定义,了解默认的 ON UPDATE 行为
rg -n "CREATE PROCEDURE.*ADD_CONSTRAINT\|CREATE FUNCTION.*ADD_CONSTRAINT" conf/db/ --glob "*.sql" -A 20
# 查看所有提到 provisionNicUuid 的脚本
grep -r "provisionNicUuid" conf/db/upgrade/ --include="*.sql"
# 检查 BareMetal2BondingNicRefVO 在其他版本中是否有修改
rg -n "BareMetal2BondingNicRefVO" conf/db/upgrade/ --glob "*.sql"Repository: MatheMatrix/zstack Length of output: 958 🏁 Script executed: # 查看 FK 的完整定义,包括 ON UPDATE 和 ON DELETE 选项
rg -n "fkBareMetal2BondingNicRefVOProvisionNicVO\|FOREIGN KEY.*provisionNicUuid" conf/db/upgrade/ --glob "*.sql" -B 3 -A 3Repository: MatheMatrix/zstack Length of output: 44 🏁 Script executed: # 查看 V5.5.6 脚本的完整内容,确保没有遗漏任何 FK 处理
sed -n '1,80p' conf/db/upgrade/V5.5.6__schema.sqlRepository: MatheMatrix/zstack Length of output: 2996 🏁 Script executed: # 查找 ADD_CONSTRAINT 函数的实现
rg -n "CREATE PROCEDURE\|CREATE FUNCTION" conf/db/ --glob "*.sql" -A 10 | grep -A 10 "ADD_CONSTRAINT"
# 直接查看初始化脚本或工具脚本
fd "init.*\.sql\|tool.*\.sql\|procedure" conf/db/ --type f -x head -20 {}Repository: MatheMatrix/zstack Length of output: 44 🏁 Script executed: # 检查是否有其他脚本中处理了 BareMetal2BondingNicRefVO 的 provisionNicUuid
for file in conf/db/upgrade/V*.sql; do
if grep -q "provisionNicUuid\|BareMetal2BondingNicRefVO" "$file"; then
echo "=== $file ==="
grep -n "provisionNicUuid\|BareMetal2BondingNicRefVO" "$file"
fi
done
# 查看是否有删除或修改这个 FK 的操作
rg -n "DROP.*fkBareMetal2BondingNicRefVOProvisionNicVO\|ALTER TABLE.*BareMetal2BondingNicRefVO" conf/db/upgrade/ --glob "*.sql"Repository: MatheMatrix/zstack Length of output: 570 🏁 Script executed: # 查找初始化脚本中 ADD_CONSTRAINT 的定义
find conf/db -name "*.sql" -type f | xargs grep -l "CREATE PROCEDURE.*ADD_CONSTRAINT" | head -1 | xargs cat | head -100Repository: MatheMatrix/zstack Length of output: 2994 🏁 Script executed: # 查找 ADD_CONSTRAINT 函数的完整定义,特别是关于 ON UPDATE 的部分
rg -n "DROP PROCEDURE.*ADD_CONSTRAINT|CREATE PROCEDURE.*ADD_CONSTRAINT" conf/db/ --glob "*.sql" -A 50 | head -100Repository: MatheMatrix/zstack Length of output: 3762 🏁 Script executed: # 也可以从所有 SQL 文件中搜索
cat conf/db/init.sql 2>/dev/null | grep -A 50 "ADD_CONSTRAINT" | head -100Repository: MatheMatrix/zstack Length of output: 44 🏁 Script executed: # 如果 init.sql 不存在,查找所有包含 ADD_CONSTRAINT 定义的文件
find conf/db -name "*.sql" -type f -exec grep -l "CREATE PROCEDURE.*ADD_CONSTRAINT\|DROP PROCEDURE.*ADD_CONSTRAINT" {} \;Repository: MatheMatrix/zstack Length of output: 95 🏁 Script executed: # 查看 ADD_CONSTRAINT 的完整定义,确认是否包含 ON UPDATE 部分
sed -n '184,213p' conf/db/upgrade/beforeMigrate.sql
# 检查是否在其他脚本中修改或删除了 fkBareMetal2BondingNicRefVOProvisionNicVO
rg -n "fkBareMetal2BondingNicRefVOProvisionNicVO" conf/db/ --glob "*.sql" -B 2 -A 2
# 查看所有涉及 uuid 列修改的升级脚本,看是否有处理 FK 的模式
rg -n "UPDATE.*uuid.*REPLACE\|UPDATE.*uuid.*UUID" conf/db/upgrade/ --glob "*.sql" -B 5 -A 2Repository: MatheMatrix/zstack Length of output: 1631 🏁 Script executed: # 确认 MySQL 的默认 FK ON UPDATE 行为
# 查看脚本中是否有 ON UPDATE CASCADE 的其他示例
rg -n "ON UPDATE CASCADE\|ON UPDATE RESTRICT\|ON UPDATE" conf/db/upgrade/ --glob "*.sql" | head -20Repository: MatheMatrix/zstack Length of output: 44 🏁 Script executed: # 检查是否有其他地方更新了 provisionNicUuid
rg -n "provisionNicUuid" conf/db/upgrade/ --glob "*.sql"
# 查看 MySQL FK 的默认行为,搜索是否有文档说明
rg -n "ON UPDATE" conf/db/upgrade/ --glob "*.sql"Repository: MatheMatrix/zstack Length of output: 50374 🏁 Script executed: # 最重要的:检查 V5.5.6 脚本执行时是否会因为 FK 约束而失败
# 看看脚本中是否在更新 uuid 之前处理了 BareMetal2BondingNicRefVO 的 FK
# 完整查看 V5.5.6 脚本的 IF 块逻辑
cat conf/db/upgrade/V5.5.6__schema.sql | sed -n '30,44p'Repository: MatheMatrix/zstack Length of output: 763 处理未考虑到的外键约束导致 uuid 更新失败 此脚本删除了 需要在更新 uuid 之前处理此 FK 约束,可选方案:
|
||
| END IF; | ||
|
|
||
| SELECT COUNT(*) | ||
| INTO isPrimaryProvisionNic_exists_in_ProvisionNicVO | ||
| FROM INFORMATION_SCHEMA.COLUMNS | ||
| WHERE TABLE_SCHEMA = 'zstack' | ||
| AND TABLE_NAME = 'BareMetal2InstanceProvisionNicVO' | ||
| AND COLUMN_NAME = 'isPrimaryProvisionNic'; | ||
|
|
||
| IF isPrimaryProvisionNic_exists_in_ProvisionNicVO = 0 THEN | ||
| CALL ADD_COLUMN('BareMetal2InstanceProvisionNicVO', 'isPrimaryProvisionNic', 'BOOLEAN', FALSE, FALSE); | ||
|
|
||
| UPDATE `zstack`.`BareMetal2InstanceProvisionNicVO` | ||
| SET `isPrimaryProvisionNic` = TRUE; | ||
| END IF; | ||
|
|
||
| SELECT COUNT(*) | ||
| INTO isPrimaryProvisionNic_exists_in_ChassisNicVO | ||
| FROM INFORMATION_SCHEMA.COLUMNS | ||
| WHERE TABLE_SCHEMA = 'zstack' | ||
| AND TABLE_NAME = 'BareMetal2ChassisNicVO' | ||
| AND COLUMN_NAME = 'isPrimaryProvisionNic'; | ||
|
|
||
| IF isPrimaryProvisionNic_exists_in_ChassisNicVO = 0 THEN | ||
| CALL ADD_COLUMN('BareMetal2ChassisNicVO', 'isPrimaryProvisionNic', 'BOOLEAN', FALSE, FALSE); | ||
|
|
||
| UPDATE `zstack`.`BareMetal2ChassisNicVO` | ||
| SET `isPrimaryProvisionNic` = TRUE | ||
| WHERE `isProvisionNic` = TRUE; | ||
| END IF; | ||
|
|
||
| COMMIT; | ||
| END$$ | ||
|
|
||
| DELIMITER ; | ||
| CALL UpdateBareMetal2InstanceProvisionNicVO(); | ||
| DROP PROCEDURE IF EXISTS UpdateBareMetal2InstanceProvisionNicVO; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -54,8 +54,12 @@ | |
| import org.zstack.header.storage.primary.*; | ||
| import org.zstack.header.storage.primary.VolumeSnapshotCapability.VolumeSnapshotArrangementType; | ||
| import org.zstack.header.storage.snapshot.*; | ||
| import org.zstack.header.tag.SystemTagVO; | ||
| import org.zstack.header.tag.SystemTagVO_; | ||
| import org.zstack.header.vm.VmInstanceSpec; | ||
| import org.zstack.header.vm.VmInstanceSpec.ImageSpec; | ||
| import org.zstack.header.vm.VmInstanceVO; | ||
| import org.zstack.header.vm.VmInstanceVO_; | ||
| import org.zstack.header.vo.ResourceVO; | ||
| import org.zstack.header.volume.*; | ||
| import org.zstack.identity.AccountManager; | ||
|
|
@@ -485,6 +489,8 @@ public static class CloneRsp extends AgentResponse { | |
| public Long size; | ||
| public Long actualSize; | ||
| public String installPath; | ||
| public String volumeId; | ||
| public String volumeStatus; | ||
|
|
||
| public String getInstallPath() { | ||
| return installPath; | ||
|
|
@@ -493,6 +499,22 @@ public String getInstallPath() { | |
| public void setInstallPath(String installPath) { | ||
| this.installPath = installPath; | ||
| } | ||
|
|
||
| public String getVolumeId() { | ||
| return volumeId; | ||
| } | ||
|
|
||
| public void setVolumeId(String volumeId) { | ||
| this.volumeId = volumeId; | ||
| } | ||
|
|
||
| public String getVolumeStatus() { | ||
| return volumeStatus; | ||
| } | ||
|
|
||
| public void setVolumeStatus(String volumeStatus) { | ||
| this.volumeStatus = volumeStatus; | ||
| } | ||
| } | ||
|
|
||
| public static class FlattenCmd extends AgentCommand implements HasThreadContext { | ||
|
|
@@ -2636,6 +2658,40 @@ public void run(final FlowTrigger trigger, Map data) { | |
| CloneCmd cmd = new CloneCmd(); | ||
| cmd.srcPath = cloneInstallPath; | ||
| cmd.dstPath = volumePath; | ||
| List<CephPrimaryStorageCheckInstanceTypeExtensionPoint> exts = pluginRgty.getExtensionList(CephPrimaryStorageCheckInstanceTypeExtensionPoint.class); | ||
| for (CephPrimaryStorageCheckInstanceTypeExtensionPoint ext : exts) { | ||
| Boolean result = ext.isSupportCloneByThirdParty(msg.getVolume().getVmInstanceUuid()); | ||
| if (!result) { | ||
| break; | ||
| } | ||
| boolean isRootVolume = Q.New(VolumeVO.class) | ||
| .eq(VolumeVO_.uuid, msg.getVolume().getUuid()) | ||
| .eq(VolumeVO_.type, VolumeType.Root) | ||
| .isExists(); | ||
| boolean isBareMetal2Instance = Q.New(VmInstanceVO.class) | ||
| .eq(VmInstanceVO_.uuid, msg.getVolume().getVmInstanceUuid()) | ||
| .eq(VmInstanceVO_.type, "baremetal2") | ||
| .isExists(); | ||
| boolean hasToken = CephSystemTags.THIRDPARTY_PLATFORM.hasTag(msg.getPrimaryStorageUuid()); | ||
| if (isRootVolume && isBareMetal2Instance && hasToken) { | ||
| CephPrimaryStorageVO cephPrimaryStorageVO = dbf.findByUuid(msg.getPrimaryStorageUuid(), CephPrimaryStorageVO.class); | ||
| String monIp = cephPrimaryStorageVO.getMons() | ||
| .stream() | ||
| .filter(v -> v.getStatus() == MonStatus.Connected) | ||
| .map(CephPrimaryStorageMonVO::getHostname) | ||
| .findAny() | ||
| .orElseThrow(() -> new OperationFailureException( | ||
| operr("all ceph mons of primary storage[uuid:%s] are not in Connected state", cephPrimaryStorageVO.getUuid()) | ||
| )); | ||
| cmd.token = CephSystemTags.THIRDPARTY_PLATFORM.getTokenByResourceUuid(msg.getPrimaryStorageUuid(), | ||
| CephSystemTags.THIRDPARTY_PLATFORM_TOKEN); | ||
| cmd.monIp = monIp; | ||
| cmd.tpTimeout = CephGlobalConfig.THIRD_PARTY_SDK_TIMEOUT.value(String.class); | ||
| VolumeVO vo = Q.New(VolumeVO.class) | ||
| .eq(VolumeVO_.uuid, msg.getVolume().getUuid()).find(); | ||
| ext.convertToBlockVolume(vo); | ||
|
Comment on lines
+2676
to
+2692
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
修复方向(示例):HttpCaller 仅在 monIp 为空时填充- cmd.monUuid = base.getSelf().getUuid();
- cmd.monIp = base.getSelf().getHostname();
+ cmd.monUuid = base.getSelf().getUuid();
+ if (cmd.monIp == null) {
+ cmd.monIp = base.getSelf().getHostname();
+ }如果 monIp 语义需要区分“ceph mon 用于 httpCall 的地址”和“第三方平台 SDK 需要的 monIp”,建议新增独立字段(例如 Also applies to: 3624-3636 🤖 Prompt for AI Agents |
||
| } | ||
|
Comment on lines
+2676
to
+2693
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| } | ||
|
Comment on lines
+2661
to
+2694
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 第三方 clone 扩展点循环的控制流有明显 bug:
可行修复(continue + null-safe + 提前计算条件)- List<CephPrimaryStorageCheckInstanceTypeExtensionPoint> exts = pluginRgty.getExtensionList(CephPrimaryStorageCheckInstanceTypeExtensionPoint.class);
- for (CephPrimaryStorageCheckInstanceTypeExtensionPoint ext : exts) {
- Boolean result = ext.isSupportCloneByThirdParty(msg.getVolume().getVmInstanceUuid());
- if (!result) {
- break;
- }
- boolean isRootVolume = Q.New(VolumeVO.class)
- .eq(VolumeVO_.uuid, msg.getVolume().getUuid())
- .eq(VolumeVO_.type, VolumeType.Root)
- .isExists();
- boolean isBareMetal2Instance = Q.New(VmInstanceVO.class)
- .eq(VmInstanceVO_.uuid, msg.getVolume().getVmInstanceUuid())
- .eq(VmInstanceVO_.type, "baremetal2")
- .isExists();
- boolean hasToken = CephSystemTags.THIRDPARTY_PLATFORM.hasTag(msg.getPrimaryStorageUuid());
- if (isRootVolume && isBareMetal2Instance && hasToken) {
+ List<CephPrimaryStorageCheckInstanceTypeExtensionPoint> exts =
+ pluginRgty.getExtensionList(CephPrimaryStorageCheckInstanceTypeExtensionPoint.class);
+
+ boolean isRootVolume = Q.New(VolumeVO.class)
+ .eq(VolumeVO_.uuid, msg.getVolume().getUuid())
+ .eq(VolumeVO_.type, VolumeType.Root)
+ .isExists();
+ boolean isBareMetal2Instance = Q.New(VmInstanceVO.class)
+ .eq(VmInstanceVO_.uuid, msg.getVolume().getVmInstanceUuid())
+ .eq(VmInstanceVO_.type, "baremetal2")
+ .isExists();
+ boolean hasToken = CephSystemTags.THIRDPARTY_PLATFORM.hasTag(msg.getPrimaryStorageUuid());
+
+ for (CephPrimaryStorageCheckInstanceTypeExtensionPoint ext : exts) {
+ if (!Boolean.TRUE.equals(ext.isSupportCloneByThirdParty(msg.getVolume().getVmInstanceUuid()))) {
+ continue;
+ }
+ if (isRootVolume && isBareMetal2Instance && hasToken) {
CephPrimaryStorageVO cephPrimaryStorageVO = dbf.findByUuid(msg.getPrimaryStorageUuid(), CephPrimaryStorageVO.class);
String monIp = cephPrimaryStorageVO.getMons()
.stream()
.filter(v -> v.getStatus() == MonStatus.Connected)
.map(CephPrimaryStorageMonVO::getHostname)
.findAny()
.orElseThrow(() -> new OperationFailureException(
operr("all ceph mons of primary storage[uuid:%s] are not in Connected state", cephPrimaryStorageVO.getUuid())
));
cmd.token = CephSystemTags.THIRDPARTY_PLATFORM.getTokenByResourceUuid(msg.getPrimaryStorageUuid(),
CephSystemTags.THIRDPARTY_PLATFORM_TOKEN);
cmd.monIp = monIp;
cmd.tpTimeout = CephGlobalConfig.THIRD_PARTY_SDK_TIMEOUT.value(String.class);
VolumeVO vo = Q.New(VolumeVO.class)
.eq(VolumeVO_.uuid, msg.getVolume().getUuid()).find();
ext.convertToBlockVolume(vo);
}
}另外强烈建议把 |
||
|
|
||
| httpCall(CLONE_PATH, cmd, CloneRsp.class, new ReturnValueCompletion<CloneRsp>(trigger) { | ||
| @Override | ||
|
|
@@ -2646,6 +2702,14 @@ public void fail(ErrorCode err) { | |
| @Override | ||
| public void success(CloneRsp ret) { | ||
| actualSize = ret.actualSize; | ||
| List<CephPrimaryStorageCheckInstanceTypeExtensionPoint> exts = pluginRgty.getExtensionList(CephPrimaryStorageCheckInstanceTypeExtensionPoint.class); | ||
| for (CephPrimaryStorageCheckInstanceTypeExtensionPoint ext : exts) { | ||
| if (!ext.isBlockVolume(msg.getVolume().getUuid())) { | ||
| break; | ||
| } | ||
| volumePath = ret.installPath == null ? volumePath : makeVolumeInstallPathByTargetPool(ret.installPath, targetCephPoolName); | ||
| ext.populateBlockVolumeDetails(msg.getVolume().getUuid(), ret.volumeId, ret.volumeStatus); | ||
| } | ||
|
Comment on lines
+2705
to
+2712
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 成功回调里的扩展点循环同样不应
可行修复(continue + installPath 前缀判断) List<CephPrimaryStorageCheckInstanceTypeExtensionPoint> exts = pluginRgty.getExtensionList(CephPrimaryStorageCheckInstanceTypeExtensionPoint.class);
for (CephPrimaryStorageCheckInstanceTypeExtensionPoint ext : exts) {
if (!ext.isBlockVolume(msg.getVolume().getUuid())) {
- break;
+ continue;
}
- volumePath = ret.installPath == null ? volumePath : makeVolumeInstallPathByTargetPool(ret.installPath, targetCephPoolName);
+ if (ret.installPath != null) {
+ volumePath = ret.installPath.startsWith("ceph://")
+ ? ret.installPath
+ : makeVolumeInstallPathByTargetPool(ret.installPath, targetCephPoolName);
+ }
ext.populateBlockVolumeDetails(msg.getVolume().getUuid(), ret.volumeId, ret.volumeStatus);
}🤖 Prompt for AI Agents |
||
| trigger.next(); | ||
| } | ||
| }); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| package org.zstack.storage.ceph.primary; | ||
|
|
||
| import org.zstack.header.volume.VolumeVO; | ||
|
|
||
| public interface CephPrimaryStorageCheckInstanceTypeExtensionPoint { | ||
| Boolean isSupportCloneByThirdParty(String uuid); | ||
|
|
||
| void convertToBlockVolume(VolumeVO vo); | ||
|
|
||
| Boolean isBlockVolume(String uuid); | ||
|
|
||
| void populateBlockVolumeDetails(String uuid, String volumeId, String volumeStatus); | ||
| } | ||
|
Comment on lines
+5
to
+13
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion | 🟠 Major 建议把
Proposed diff public interface CephPrimaryStorageCheckInstanceTypeExtensionPoint {
- Boolean isSupportCloneByThirdParty(String uuid);
+ boolean isSupportCloneByThirdParty(String vmInstanceUuid);
- void convertToBlockVolume(VolumeVO vo);
+ void convertToBlockVolume(VolumeVO volume);
- Boolean isBlockVolume(String uuid);
+ boolean isBlockVolume(String volumeUuid);
- void populateBlockVolumeDetails(String uuid, String volumeId, String volumeStatus);
+ void populateBlockVolumeDetails(String volumeUuid, String volumeId, String volumeStatus);
}🤖 Prompt for AI Agents |
||
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.
DROP FOREIGN KEY 缺少存在性检查,可能导致执行失败
当外键
fkBareMetal2InstanceProvisionNicVOInstanceVO不存在时(例如新数据库或脚本重复执行),此语句会抛出异常。建议在执行前检查外键是否存在:
🔧 建议修复:添加外键存在性检查
IF instanceUuid_exists = 0 THEN CALL ADD_COLUMN('BareMetal2InstanceProvisionNicVO', 'instanceUuid', 'VARCHAR(32)', FALSE, ''); UPDATE `zstack`.`BareMetal2InstanceProvisionNicVO` SET `instanceUuid` = `uuid`; + -- Check if foreign key exists before dropping + IF EXISTS ( + SELECT 1 FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS + WHERE TABLE_SCHEMA = 'zstack' + AND TABLE_NAME = 'BareMetal2InstanceProvisionNicVO' + AND CONSTRAINT_NAME = 'fkBareMetal2InstanceProvisionNicVOInstanceVO' + AND CONSTRAINT_TYPE = 'FOREIGN KEY' + ) THEN ALTER TABLE `zstack`.`BareMetal2InstanceProvisionNicVO` DROP FOREIGN KEY `fkBareMetal2InstanceProvisionNicVOInstanceVO`; + END IF; CALL ADD_CONSTRAINT('BareMetal2InstanceProvisionNicVO', 'fkBareMetal2InstanceProvisionNicVOInstanceVO', 'instanceUuid', 'BareMetal2InstanceVO', 'uuid', 'CASCADE'); UPDATE `zstack`.`BareMetal2InstanceProvisionNicVO` SET `uuid` = REPLACE(UUID(), '-', ''); END IF;📝 Committable suggestion
🤖 Prompt for AI Agents