Skip to content

Conversation

@DaanHoogland
Copy link
Contributor

Description

This PR...

Fixes: #11973

Types of changes

  • Breaking change (fix or feature that would cause existing functionality to change)
  • New feature (non-breaking change which adds functionality)
  • Bug fix (non-breaking change which fixes an issue)
  • Enhancement (improves an existing feature and functionality)
  • Cleanup (Code refactoring and cleanup, that may add test cases)
  • Build/CI
  • Test (unit or integration test code)

Feature/Enhancement Scale or Bug Severity

Feature/Enhancement Scale

  • Major
  • Minor

Bug Severity

  • BLOCKER
  • Critical
  • Major
  • Minor
  • Trivial

Screenshots (if appropriate):

How Has This Been Tested?

How did you try to break this feature and the system with this change?

@codecov
Copy link

codecov bot commented Nov 26, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 4.00%. Comparing base (028dd86) to head (2135e1e).

❗ There is a different number of reports uploaded between BASE (028dd86) and HEAD (2135e1e). Click for more details.

HEAD has 1 upload less than BASE
Flag BASE (028dd86) HEAD (2135e1e)
unittests 1 0
Additional details and impacted files
@@              Coverage Diff              @@
##               4.20   #12140       +/-   ##
=============================================
- Coverage     16.18%    4.00%   -12.18%     
=============================================
  Files          5657      402     -5255     
  Lines        498470    32665   -465805     
  Branches      60493     5808    -54685     
=============================================
- Hits          80660     1309    -79351     
+ Misses       408830    31203   -377627     
+ Partials       8980      153     -8827     
Flag Coverage Δ
uitests 4.00% <ø> (ø)
unittests ?

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds a check to prevent database upgrades from running when multiple management servers are active. The implementation verifies that only one management server with status 'UP' exists in the database before proceeding with the upgrade process, addressing issue #11973.

  • Extracts the upgrade logic into a new doUpgrades() method for better code organization
  • Introduces checkIfStandalone() to query the management_server table and enforce single-server mode
  • Throws an exception if multiple active management servers are detected, preventing concurrent upgrade attempts

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 462 to 480
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;
}
});
Copy link

Copilot AI Nov 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Transaction.execute() wrapper is unnecessary here. The code inside the callback is obtaining its own standalone connection via TransactionLegacy.getStandaloneConnection(), which means the transaction context provided by Transaction.execute() is not being used.

Consider simplifying this to directly execute the query without the Transaction.execute wrapper, or use the TransactionStatus parameter properly if transaction management is needed.

Suggested change
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;
}
});
String sql = "SELECT COUNT(*) FROM `cloud`.`management_server` WHERE `status` = 'UP'";
boolean standalone = true;
try (Connection conn = TransactionLegacy.getStandaloneConnection();
PreparedStatement pstmt = conn.prepareStatement(sql);
ResultSet rs = pstmt.executeQuery()) {
if (rs.next()) {
int count = rs.getInt(1);
standalone = 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);
}

Copilot uses AI. Check for mistakes.
Comment on lines 461 to 486
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);
}
}
Copy link

Copilot AI Nov 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new checkIfStandalone() method lacks test coverage. Consider adding unit tests to verify:

  1. The behavior when no management servers are running (count = 0)
  2. The behavior when exactly one management server is running (count = 1)
  3. The behavior when multiple management servers are running (count > 1)
  4. The behavior when a SQLException occurs during the check

This is particularly important since this check prevents upgrades from proceeding when multiple servers are detected.

Copilot uses AI. Check for mistakes.
@DaanHoogland DaanHoogland requested a review from Copilot November 27, 2025 15:44
Copilot finished reviewing on behalf of DaanHoogland November 27, 2025 15:45
@apache apache deleted a comment from blueorangutan Nov 27, 2025
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated 1 comment.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@blueorangutan
Copy link

Packaging result [SF]: ✖️ el8 ✖️ el9 ✖️ debian ✖️ suse15. SL-JID 15845

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