-
Notifications
You must be signed in to change notification settings - Fork 0
<fix>[ceph]: support thirdparty_ceph to bm root volume #3214
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 |
|---|---|---|
|
|
@@ -6,3 +6,78 @@ ALTER TABLE `GuestVmScriptExecutedRecordDetailVO` | |
|
|
||
| CALL ADD_COLUMN('PciDeviceVO', 'vmPciDeviceAddress', 'varchar(32)', 1, NULL); | ||
| CALL ADD_COLUMN('MdevDeviceVO', 'mdevDeviceAddress', 'varchar(32)', 1, NULL); | ||
|
|
||
| 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'); | ||
|
|
||
| UPDATE `zstack`.`BareMetal2InstanceProvisionNicVO` | ||
| SET `uuid` = REPLACE(UUID(), '-', ''); | ||
|
Comment on lines
+36
to
+46
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
# 检索数据库升级脚本中对 BareMetal2InstanceProvisionNicVO 的引用
echo "=== SQL 脚本中的引用 ==="
rg -n --type=sql 'BareMetal2InstanceProvisionNicVO' -C2
echo ""
echo "=== Java 代码中的引用 ==="
rg -n --type=java 'BareMetal2InstanceProvisionNicVO' -C2
echo ""
echo "=== 相关的字段引用 ==="
rg -n --type=java 'bareMetal2InstanceProvisionNic|provisionNicUuid' -C1Repository: MatheMatrix/zstack Length of output: 6855 🏁 Script executed: cat -n conf/db/upgrade/V5.5.6__schema.sqlRepository: MatheMatrix/zstack Length of output: 3556 🏁 Script executed: #!/bin/bash
# 查看 BareMetal2BondingNicRefVO 的表定义
echo "=== BareMetal2BondingNicRefVO 表定义 ==="
rg -n --type=sql 'CREATE TABLE.*BareMetal2BondingNicRefVO|CREATE TABLE.*IF NOT EXISTS.*BareMetal2BondingNicRefVO' -A 20
echo ""
echo "=== 查看所有升级脚本中对 BareMetal2BondingNicRefVO 的修改 ==="
rg -n --type=sql 'BareMetal2BondingNicRefVO' -B 2 -A 2Repository: MatheMatrix/zstack Length of output: 3202 🏁 Script executed: #!/bin/bash
# 查看 V5.5.6 之后的升级脚本是否有处理 provisionNicUuid
echo "=== V5.5.6 之后的升级脚本 ==="
fd --type f 'V[0-9]+\.[0-9]+\.[0-9]+__schema\.sql' conf/db/upgrade | sort | tail -10
echo ""
echo "=== 搜索升级脚本中对 provisionNicUuid 的更新 ==="
rg -n --type=sql 'provisionNicUuid' -B 2 -A 2
echo ""
echo "=== 检查是否在升级脚本中有其他对 BareMetal2BondingNicRefVO 的更新 ==="
rg -n --type=sql 'UPDATE.*BareMetal2BondingNicRefVO|UPDATE.*provisionNicUuid' -B 2 -A 2Repository: MatheMatrix/zstack Length of output: 1045 🏁 Script executed: #!/bin/bash
# 查看外键约束的完整定义
echo "=== 外键约束定义 ==="
rg -n --type=sql "FOREIGN KEY.*BareMetal2InstanceProvisionNicVO.*uuid" -B 2 -A 2
echo ""
echo "=== 确认约束配置中是否有 ON UPDATE CASCADE ==="
rg -n --type=sql "fkBareMetal2BondingNicRefVOProvisionNicVO" -B 2 -A 2
# 查看 ADD_CONSTRAINT 函数的定义
echo ""
echo "=== 查找 ADD_CONSTRAINT 存储过程的定义 ==="
rg -n --type=sql "CREATE PROCEDURE.*ADD_CONSTRAINT|PROCEDURE.*ADD_CONSTRAINT" -A 30 | head -60Repository: MatheMatrix/zstack Length of output: 3097 🏁 Script executed: #!/bin/bash
# 详细查看 ADD_CONSTRAINT 的完整实现
sed -n '187,212p' conf/db/upgrade/beforeMigrate.sql
echo ""
echo "=== 确认当前是否有 ON UPDATE 处理 ==="
grep -n "ON UPDATE" conf/db/upgrade/beforeMigrate.sqlRepository: MatheMatrix/zstack Length of output: 1118 在重置 uuid 前需同步更新引用该字段的表。
升级脚本在第 42-43 行直接更新 uuid 为新值,会导致 需在更新 uuid 之前,先同步更新所有引用该字段的表中的值,或在升级脚本中先删除外键再重建。 🤖 Prompt for AI Agents |
||
| 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; | ||
|
Comment on lines
+18
to
+78
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. DDL 隐式提交会让事务回滚失效。 此处在事务内执行 ALTER TABLE / ADD_COLUMN 等 DDL,MySQL/MariaDB 会隐式 COMMIT,EXIT HANDLER 的 ROLLBACK 无法还原已执行的 DDL,升级中断可能留下半完成状态。建议移除事务假象或改为可逆、分步且幂等的升级方案。Based on learnings, ... 🤖 Prompt for AI Agents |
||
| 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
+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. 扩展点遍历不应使用 当前在遇到 🐛 建议修改- for (CephPrimaryStorageCheckInstanceTypeExtensionPoint ext : exts) {
- Boolean result = ext.isSupportCloneByThirdParty(msg.getVolume().getVmInstanceUuid());
- if (!result) {
- break;
- }
+ for (CephPrimaryStorageCheckInstanceTypeExtensionPoint ext : exts) {
+ if (!Boolean.TRUE.equals(ext.isSupportCloneByThirdParty(msg.getVolume().getVmInstanceUuid()))) {
+ continue;
+ }
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) {
...
}
}- for (CephPrimaryStorageCheckInstanceTypeExtensionPoint ext : exts) {
- if (!ext.isBlockVolume(msg.getVolume().getUuid())) {
- break;
- }
+ for (CephPrimaryStorageCheckInstanceTypeExtensionPoint ext : exts) {
+ if (!Boolean.TRUE.equals(ext.isBlockVolume(msg.getVolume().getUuid()))) {
+ continue;
+ }
volumePath = ret.installPath == null ? volumePath : makeVolumeInstallPathByTargetPool(ret.installPath, targetCephPoolName);
ext.populateBlockVolumeDetails(msg.getVolume().getUuid(), ret.volumeId, ret.volumeStatus);
}Also applies to: 2705-2712 🤖 Prompt for AI Agents |
||
|
|
||
| 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); | ||
| } | ||
| 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
+12
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: # 查找接口实现类
rg -n --type=java 'implements\s+CephPrimaryStorageCheckInstanceTypeExtensionPoint' -A 3Repository: MatheMatrix/zstack Length of output: 44 🏁 Script executed: # 查找接口方法的调用
rg -n --type=java '\.isSupportCloneByThirdParty\(|\.isBlockVolume\(' -B 2 -A 2Repository: MatheMatrix/zstack Length of output: 1892 🏁 Script executed: # 查找接口的注入和使用
rg -n --type=java 'CephPrimaryStorageCheckInstanceTypeExtensionPoint'Repository: MatheMatrix/zstack Length of output: 1157 🏁 Script executed: # 检查当前文件的完整内容和是否有其他定义
cat -n plugin/ceph/src/main/java/org/zstack/storage/ceph/primary/CephPrimaryStorageCheckInstanceTypeExtensionPoint.javaRepository: MatheMatrix/zstack Length of output: 536 🏁 Script executed: # 查找接口实现类
find . -name "*.java" -type f -exec grep -l "implements.*CephPrimaryStorageCheckInstanceTypeExtensionPoint" {} \;Repository: MatheMatrix/zstack Length of output: 44 🏁 Script executed: # 检查具体的调用代码上下文
sed -n '2660,2710p' plugin/ceph/src/main/java/org/zstack/storage/ceph/primary/CephPrimaryStorageBase.javaRepository: MatheMatrix/zstack Length of output: 3914 🏁 Script executed: # 搜索所有实现该接口的类
rg -n 'class\s+\w+.*implements.*CephPrimaryStorageCheckInstanceTypeExtensionPoint' -A 10Repository: MatheMatrix/zstack Length of output: 44 将 调用代码在 建议修改- Boolean isSupportCloneByThirdParty(String uuid);
+ boolean isSupportCloneByThirdParty(String uuid);
- Boolean isBlockVolume(String uuid);
+ boolean isBlockVolume(String uuid);🤖 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 前应检查约束是否存在。
当前实现直接执行
DROP FOREIGN KEY,但未检查该外键约束是否存在。如果升级脚本部分执行后失败重试,或者数据库状态与预期不同,此操作会失败并导致整个迁移回滚。根据 ZStack 项目的最佳实践,应通过
INFORMATION_SCHEMA.TABLE_CONSTRAINTS检查约束存在性后再删除。🐛 建议的修复方案
🤖 Prompt for AI Agents