From edcbbdef0967461b3c35c74d6e66ec7e3b612876 Mon Sep 17 00:00:00 2001 From: Daan Hoogland Date: Wed, 26 Nov 2025 15:14:07 +0100 Subject: [PATCH 1/4] check for active MSses before starting DB upgrade --- .../cloud/upgrade/DatabaseUpgradeChecker.java | 83 +++++++++++++------ 1 file changed, 59 insertions(+), 24 deletions(-) diff --git a/engine/schema/src/main/java/com/cloud/upgrade/DatabaseUpgradeChecker.java b/engine/schema/src/main/java/com/cloud/upgrade/DatabaseUpgradeChecker.java index abf860439375..e99cd894a9c3 100644 --- a/engine/schema/src/main/java/com/cloud/upgrade/DatabaseUpgradeChecker.java +++ b/engine/schema/src/main/java/com/cloud/upgrade/DatabaseUpgradeChecker.java @@ -123,7 +123,10 @@ import com.cloud.utils.crypt.DBEncryptionUtil; import com.cloud.utils.db.GlobalLock; import com.cloud.utils.db.ScriptRunner; +import com.cloud.utils.db.Transaction; +import com.cloud.utils.db.TransactionCallback; import com.cloud.utils.db.TransactionLegacy; +import com.cloud.utils.db.TransactionStatus; import com.cloud.utils.exception.CloudRuntimeException; import com.google.common.annotations.VisibleForTesting; @@ -448,39 +451,71 @@ public void check() { throw new CloudRuntimeException("Unable to acquire lock to check for database integrity."); } - try { - initializeDatabaseEncryptors(); + // not sure about the right moment to do this yet + checkIfStandalone(); + doUpgrades(lock); + } finally { + lock.releaseRef(); + } + } + private void checkIfStandalone() throws CloudRuntimeException { + boolean standalone = Transaction.execute(new TransactionCallback<>() { + @Override + public Boolean doInTransaction(TransactionStatus status) { + String sql = "SELECT COUNT(*) FROM `cloud`.`management_server` WHERE `status` = 'UP'"; + try (Connection conn = TransactionLegacy.getStandaloneConnection(); + PreparedStatement pstmt = conn.prepareStatement(sql); + ResultSet rs = pstmt.executeQuery()) { + if (rs.next()) { + int count = rs.getInt(1); + return count <= 1; + } + } catch (SQLException e) { + String errorMessage = "Unable to check if the management server is running in standalone mode."; + LOGGER.error(errorMessage, e); + throw new CloudRuntimeException(errorMessage, e); + } + return true; + } + }); + if (! standalone) { + String msg = "CloudStack is running multiple management servers and attempting to upgrade. Upgrades can only be run in standalone mode. Skipping database upgrade check."; + LOGGER.info(msg); + throw new CloudRuntimeException(msg); + } + } - final CloudStackVersion dbVersion = CloudStackVersion.parse(_dao.getCurrentVersion()); - final String currentVersionValue = this.getClass().getPackage().getImplementationVersion(); + private void doUpgrades(GlobalLock lock) { + try { + initializeDatabaseEncryptors(); - if (StringUtils.isBlank(currentVersionValue)) { - return; - } + final CloudStackVersion dbVersion = CloudStackVersion.parse(_dao.getCurrentVersion()); + final String currentVersionValue = this.getClass().getPackage().getImplementationVersion(); - String csVersion = SystemVmTemplateRegistration.parseMetadataFile(); - final CloudStackVersion sysVmVersion = CloudStackVersion.parse(csVersion); - final CloudStackVersion currentVersion = CloudStackVersion.parse(currentVersionValue); - SystemVmTemplateRegistration.CS_MAJOR_VERSION = String.valueOf(sysVmVersion.getMajorRelease()) + "." + String.valueOf(sysVmVersion.getMinorRelease()); - SystemVmTemplateRegistration.CS_TINY_VERSION = String.valueOf(sysVmVersion.getPatchRelease()); + if (StringUtils.isBlank(currentVersionValue)) { + return; + } - LOGGER.info("DB version = " + dbVersion + " Code Version = " + currentVersion); + String csVersion = SystemVmTemplateRegistration.parseMetadataFile(); + final CloudStackVersion sysVmVersion = CloudStackVersion.parse(csVersion); + final CloudStackVersion currentVersion = CloudStackVersion.parse(currentVersionValue); + SystemVmTemplateRegistration.CS_MAJOR_VERSION = String.valueOf(sysVmVersion.getMajorRelease()) + "." + String.valueOf(sysVmVersion.getMinorRelease()); + SystemVmTemplateRegistration.CS_TINY_VERSION = String.valueOf(sysVmVersion.getPatchRelease()); - if (dbVersion.compareTo(currentVersion) > 0) { - throw new CloudRuntimeException("Database version " + dbVersion + " is higher than management software version " + currentVersionValue); - } + LOGGER.info("DB version = " + dbVersion + " Code Version = " + currentVersion); - if (dbVersion.compareTo(currentVersion) == 0) { - LOGGER.info("DB version and code version matches so no upgrade needed."); - return; - } + if (dbVersion.compareTo(currentVersion) > 0) { + throw new CloudRuntimeException("Database version " + dbVersion + " is higher than management software version " + currentVersionValue); + } - upgrade(dbVersion, currentVersion); - } finally { - lock.unlock(); + if (dbVersion.compareTo(currentVersion) == 0) { + LOGGER.info("DB version and code version matches so no upgrade needed."); + return; } + + upgrade(dbVersion, currentVersion); } finally { - lock.releaseRef(); + lock.unlock(); } } From 48af60a81a1c6895fb8d5b35bd75dc9de3689711 Mon Sep 17 00:00:00 2001 From: dahn Date: Thu, 27 Nov 2025 16:41:58 +0100 Subject: [PATCH 2/4] fix sql --- .../src/main/java/com/cloud/upgrade/DatabaseUpgradeChecker.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/engine/schema/src/main/java/com/cloud/upgrade/DatabaseUpgradeChecker.java b/engine/schema/src/main/java/com/cloud/upgrade/DatabaseUpgradeChecker.java index e99cd894a9c3..5bd117a34eb2 100644 --- a/engine/schema/src/main/java/com/cloud/upgrade/DatabaseUpgradeChecker.java +++ b/engine/schema/src/main/java/com/cloud/upgrade/DatabaseUpgradeChecker.java @@ -462,7 +462,7 @@ private void checkIfStandalone() throws CloudRuntimeException { boolean standalone = Transaction.execute(new TransactionCallback<>() { @Override public Boolean doInTransaction(TransactionStatus status) { - String sql = "SELECT COUNT(*) FROM `cloud`.`management_server` WHERE `status` = 'UP'"; + String sql = "SELECT COUNT(*) FROM `cloud`.`mshosts` WHERE `state` = 'UP'"; try (Connection conn = TransactionLegacy.getStandaloneConnection(); PreparedStatement pstmt = conn.prepareStatement(sql); ResultSet rs = pstmt.executeQuery()) { From 46a6f7a0fcf907385daeb85c6cd233a74f452dc9 Mon Sep 17 00:00:00 2001 From: dahn Date: Thu, 27 Nov 2025 16:43:12 +0100 Subject: [PATCH 3/4] none may be up! --- .../src/main/java/com/cloud/upgrade/DatabaseUpgradeChecker.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/engine/schema/src/main/java/com/cloud/upgrade/DatabaseUpgradeChecker.java b/engine/schema/src/main/java/com/cloud/upgrade/DatabaseUpgradeChecker.java index 5bd117a34eb2..2b7266ae75a5 100644 --- a/engine/schema/src/main/java/com/cloud/upgrade/DatabaseUpgradeChecker.java +++ b/engine/schema/src/main/java/com/cloud/upgrade/DatabaseUpgradeChecker.java @@ -468,7 +468,7 @@ public Boolean doInTransaction(TransactionStatus status) { ResultSet rs = pstmt.executeQuery()) { if (rs.next()) { int count = rs.getInt(1); - return count <= 1; + return count = 0; } } catch (SQLException e) { String errorMessage = "Unable to check if the management server is running in standalone mode."; From 2135e1ef70b7b922b68f21e82425bdfa25e1f97d Mon Sep 17 00:00:00 2001 From: dahn Date: Thu, 27 Nov 2025 17:05:20 +0100 Subject: [PATCH 4/4] Apply suggestions from code review Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../java/com/cloud/upgrade/DatabaseUpgradeChecker.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/engine/schema/src/main/java/com/cloud/upgrade/DatabaseUpgradeChecker.java b/engine/schema/src/main/java/com/cloud/upgrade/DatabaseUpgradeChecker.java index 2b7266ae75a5..1e473b14063f 100644 --- a/engine/schema/src/main/java/com/cloud/upgrade/DatabaseUpgradeChecker.java +++ b/engine/schema/src/main/java/com/cloud/upgrade/DatabaseUpgradeChecker.java @@ -462,13 +462,13 @@ private void checkIfStandalone() throws CloudRuntimeException { boolean standalone = Transaction.execute(new TransactionCallback<>() { @Override public Boolean doInTransaction(TransactionStatus status) { - String sql = "SELECT COUNT(*) FROM `cloud`.`mshosts` WHERE `state` = 'UP'"; - try (Connection conn = TransactionLegacy.getStandaloneConnection(); + String sql = "SELECT COUNT(*) FROM `cloud`.`mshost` WHERE `state` = 'UP'"; + try (Connection conn = TransactionLegacy.getStandaloneConnection(); PreparedStatement pstmt = conn.prepareStatement(sql); ResultSet rs = pstmt.executeQuery()) { if (rs.next()) { int count = rs.getInt(1); - return count = 0; + return count == 0; } } catch (SQLException e) { String errorMessage = "Unable to check if the management server is running in standalone mode."; @@ -479,7 +479,7 @@ public Boolean doInTransaction(TransactionStatus status) { } }); if (! standalone) { - String msg = "CloudStack is running multiple management servers and attempting to upgrade. Upgrades can only be run in standalone mode. Skipping database upgrade check."; + String msg = "CloudStack is running multiple management servers while attempting to upgrade. Upgrades can only be run in standalone mode. Aborting."; LOGGER.info(msg); throw new CloudRuntimeException(msg); }