Skip to content

alert messages restructure - #13775

Open
DaanHoogland wants to merge 18 commits into
mainfrom
ghi7297-messages
Open

alert messages restructure#13775
DaanHoogland wants to merge 18 commits into
mainfrom
ghi7297-messages

Conversation

@DaanHoogland

Copy link
Copy Markdown
Contributor

Description

This PR...

Fixes: #7297

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?

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Note

Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.

Restructures several alert/log messages to be more consistent and information-rich, and introduces a shared formatter for host location descriptions (fixing CLOUDSTACK-7297).

Changes:

  • Added AlertFormatUtils.describeHostLocation(...) and reused it in HA/agent/orchestration alert call sites.
  • Updated many alerts/logs to include object context (e.g., host, domain, account) rather than only IDs/UUIDs.
  • Tweaked multiple failure/permission messages to improve operator readability.

Reviewed changes

Copilot reviewed 20 out of 20 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
server/src/main/java/org/apache/cloudstack/outofbandmanagement/OutOfBandManagementServiceImpl.java Updates host degraded/removed debug message formatting.
server/src/main/java/org/apache/cloudstack/ha/provider/host/HAAbstractHostProvider.java Simplifies HA fencing/recovery alert subject/body to include host object.
server/src/main/java/org/apache/cloudstack/ca/CAManagerImpl.java Improves SSH provisioning error context by logging the host object.
server/src/main/java/com/cloud/vm/UserVmManagerImpl.java Reworks several VM/host dedication alert messages; adds account/domain lookups for richer output.
server/src/main/java/com/cloud/storage/snapshot/SnapshotManagerImpl.java Updates snapshot limit alert to reference account object.
server/src/main/java/com/cloud/resourcelimit/ResourceLimitManagerImpl.java Updates permission-denied exception messages to include domain object.
server/src/main/java/com/cloud/ha/KVMFencer.java Updates fencing failure alerts to include host object.
server/src/main/java/com/cloud/ha/HighAvailabilityManagerImpl.java Uses AlertFormatUtils for host location in HA alerts; improves VM-stopped alert host description.
server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java Makes several validation exceptions include full entity objects (domain/network offering).
server/src/main/java/com/cloud/alert/AlertManagerImpl.java Changes alert logging to structured logging with entity objects.
plugins/storage/volume/scaleio/src/main/java/org/apache/cloudstack/storage/datastore/provider/ScaleIOHostListener.java Updates ScaleIO host/pool alerts/logs to include host object.
plugins/storage/volume/scaleio/src/main/java/org/apache/cloudstack/storage/datastore/driver/ScaleIOPrimaryDataStoreDriver.java Updates ScaleIO disconnection checks/alerts to include host/pool objects.
plugins/storage/volume/ontap/src/main/java/org/apache/cloudstack/storage/listener/OntapHostListener.java Improves Ontap attach-storage error messages by using host object.
plugins/storage/volume/datera/src/main/java/org/apache/cloudstack/storage/datastore/provider/DateraHostListener.java Improves Datera attach-storage alert message by using fetched host object.
engine/storage/volume/src/main/java/org/apache/cloudstack/storage/datastore/provider/DefaultHostListener.java Improves default host connect failure message by including host object.
engine/storage/src/main/java/org/apache/cloudstack/storage/image/BaseImageStoreDriverImpl.java Updates upload/register/copy failure alerts to include object string.
engine/storage/snapshot/src/main/java/org/apache/cloudstack/storage/vmsnapshot/ScaleIOVMSnapshotStrategy.java Clarifies VM snapshot failure message to include snapshot object context.
engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java Uses AlertFormatUtils to include host location in agent network-setup failure alert.
engine/orchestration/src/main/java/com/cloud/agent/manager/AgentManagerImpl.java Uses AlertFormatUtils for consistent host location strings in disconnect/alert-state messages.
engine/components-api/src/main/java/com/cloud/alert/AlertFormatUtils.java New shared helper for consistent host/zone/pod alert formatting.

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

Comment thread server/src/main/java/com/cloud/vm/UserVmManagerImpl.java
Comment thread server/src/main/java/com/cloud/vm/UserVmManagerImpl.java Outdated
Comment thread server/src/main/java/com/cloud/resourcelimit/ResourceLimitManagerImpl.java Outdated
Comment thread server/src/main/java/com/cloud/resourcelimit/ResourceLimitManagerImpl.java Outdated
Comment thread server/src/main/java/com/cloud/alert/AlertManagerImpl.java Outdated
Copilot AI review requested due to automatic review settings August 3, 2026 15:37

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

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 23 out of 23 changed files in this pull request and generated 1 comment.

Suppressed comments (7)

server/src/main/java/com/cloud/vm/UserVmManagerImpl.java:2869

  • The conditional uses hostId != null but prints host (object). If hostId is set but the host lookup failed, this will produce on host [null] and loses the only reliable identifier (the host id). Consider using host != null for the host-object rendering, and fall back to hostId when host is null so the alert remains actionable.
                String subject = String.format("Failed to deploy Instance [%s]", vm);
                String body = String.format("Failed to deploy [%s]%s. To troubleshoot, please check the logs with [logid:%s].",
                        vm,
                        hostId != null ? String.format(" on host [%s]", host) : "",
                        ThreadContext.get("logcontextid"));

server/src/main/java/com/cloud/vm/UserVmManagerImpl.java:7769

  • These alerts now depend on Account.toString() / Domain.toString() for human-readable names, and will render null if the DAO lookup returns null—where previously the IDs were always present. To keep alerts stable and actionable, consider formatting explicitly (e.g., account name + id, domain name + id) with a fallback to the raw IDs when the DAO lookup fails, instead of relying on toString().
            Long srcAccountId = accountOfDedicatedHost(srcHost);
            Long destAccountId = accountOfDedicatedHost(destHost);
            if (!((srcAccountId == null) || (srcAccountId.equals(destAccountId)))) {
                Account srcAccount = _accountDao.findById(srcAccountId);
                Account destAccount = _accountDao.findById(destAccountId);
                String msg = String.format("VM is being migrated from host %s explicitly dedicated to account %s to host %s explicitly dedicated to account %s",
                        srcHost, srcAccount, destHost, destAccount);

server/src/main/java/com/cloud/vm/UserVmManagerImpl.java:7779

  • These alerts now depend on Account.toString() / Domain.toString() for human-readable names, and will render null if the DAO lookup returns null—where previously the IDs were always present. To keep alerts stable and actionable, consider formatting explicitly (e.g., account name + id, domain name + id) with a fallback to the raw IDs when the DAO lookup fails, instead of relying on toString().
            Long srcDomainId = domainOfDedicatedHost(srcHost);
            Long destDomainId = domainOfDedicatedHost(destHost);
            if (!((srcDomainId == null) || (srcDomainId.equals(destDomainId)))) {
                Domain srcDomain = _domainDao.findById(srcDomainId);
                Domain destDomain = _domainDao.findById(destDomainId);
                String msg = String.format("VM is being migrated from host %s explicitly dedicated to domain %s to host %s explicitly dedicated to domain %s",
                        srcHost, srcDomain, destHost, destDomain);

server/src/test/java/com/cloud/vm/UserVmManagerImplTest.java:4597

  • This test hard-codes expectations around toString() output for AccountVO and DomainVO, which is typically not a stable API and can change without functional impact. If the production intent is to include account/domain names, it would be more robust to have production code format using explicit getters (e.g., account name / domain name) and have the test stub those getters and assert on them.
        AccountVO srcAccount = Mockito.mock(AccountVO.class);
        when(srcAccount.toString()).thenReturn("Account {accountName=account-a}");
        AccountVO destAccount = Mockito.mock(AccountVO.class);
        when(destAccount.toString()).thenReturn("Account {accountName=account-b}");

server/src/test/java/com/cloud/vm/UserVmManagerImplTest.java:4604

  • This test hard-codes expectations around toString() output for AccountVO and DomainVO, which is typically not a stable API and can change without functional impact. If the production intent is to include account/domain names, it would be more robust to have production code format using explicit getters (e.g., account name / domain name) and have the test stub those getters and assert on them.
        DomainVO srcDomain = Mockito.mock(DomainVO.class);
        when(srcDomain.toString()).thenReturn("Domain {name=domain-a}");
        DomainVO destDomain = Mockito.mock(DomainVO.class);
        when(destDomain.toString()).thenReturn("Domain {name=domain-b}");

plugins/storage/volume/datera/src/main/java/org/apache/cloudstack/storage/datastore/provider/DateraHostListener.java:301

  • If _hostDao.findById(hostId) returns null, the message will become ... to host null, which is less actionable than the previous host id-based message. Consider falling back to hostId when host is null (or rendering both: host + id) to preserve diagnostic value.
            HostVO host = _hostDao.findById(hostId);
            String msg = String.format("Unable to attach storage pool %s to host %s", storagePool, host);

engine/components-api/src/main/java/com/cloud/alert/AlertFormatUtils.java:26

  • The PR description is still the default template (type-of-change checkboxes and testing details are not filled in). Since repository automation relies on the description for labeling/documentation, please update the PR description to clearly state the functional behavior change and how it was tested.
 * Shared formatting for the host/zone/pod description that recurs, independently
 * hand-rolled and inconsistently worded (and occasionally mislabelled), across the
 * HA and agent-management alert call sites. See CLOUDSTACK-7297.

Copilot AI review requested due to automatic review settings August 3, 2026 16:05

This comment was marked as outdated.

This comment was marked as outdated.

Copilot AI review requested due to automatic review settings August 4, 2026 05:50

This comment was marked as outdated.

@apache apache deleted a comment from blueorangutan Aug 4, 2026
@apache apache deleted a comment from blueorangutan Aug 4, 2026
Copilot AI review requested due to automatic review settings August 4, 2026 09:31

This comment was marked as outdated.

@DaanHoogland DaanHoogland added this to the 4.24.0 milestone Aug 4, 2026
Copilot AI review requested due to automatic review settings August 5, 2026 08:48

This comment was marked as outdated.

Copilot AI review requested due to automatic review settings August 14, 2026 12:38

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

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 25 out of 25 changed files in this pull request and generated no new comments.

Suppressed comments (2)

server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java:4650

  • This error path explicitly allows domainId to be null, but the exception message still calls _entityMgr.findById(Domain.class, domainId). If domainId is null this can throw a NullPointerException (GenericDaoBase.findById uses cache.get(id)/lockRow(id) without null checks), preventing the intended InvalidParameterValueException from being returned.
                if (domainId == null || !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new InvalidParameterValueException(String.format("Unable to create disk offering by another domain-admin: %s for domain: %s", user, _entityMgr.findById(Domain.class, domainId)));
                }

server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java:3598

  • The exception message calls _entityMgr.findById(Domain.class, domainId) without guarding against domainId being null. DomainHelper.filterChildSubDomains can return null entries if the input list contains nulls, and GenericDaoBase.findById(null) can throw a NullPointerException (e.g., via cache access), masking the intended InvalidParameterValueException.

This issue also appears on line 4648 of the same file.

                if (!_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new InvalidParameterValueException(String.format("Unable to create service offering by another domain-admin: %s for domain: %s", user, _entityMgr.findById(Domain.class, domainId)));
                }

@apache apache deleted a comment from blueorangutan Aug 14, 2026
@apache apache deleted a comment from blueorangutan Aug 14, 2026
@apache apache deleted a comment from blueorangutan Aug 14, 2026
@apache apache deleted a comment from blueorangutan Aug 14, 2026
Copilot AI review requested due to automatic review settings August 14, 2026 13:55

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

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 25 out of 25 changed files in this pull request and generated no new comments.

Suppressed comments (5)

server/src/main/java/com/cloud/vm/UserVmManagerImpl.java:7787

  • Same as the account alert above: if domain lookup returns null, the message becomes "... dedicated to domain null ..." and loses the domain id. Adding a simple fallback keeps the alert actionable even with missing domain records.
                Domain srcDomain = _domainDao.findById(srcDomainId);
                Domain destDomain = destDomainId != null ? _domainDao.findById(destDomainId) : null;
                String msg = String.format("VM is being migrated from host %s explicitly dedicated to domain %s to host %s %s",
                        srcHost, srcDomain, destHost, destDomain != null ? "explicitly dedicated to domain " + destDomain : "not dedicated to a specific domain");

plugins/storage/volume/datera/src/main/java/org/apache/cloudstack/storage/datastore/provider/DateraHostListener.java:303

  • The failure alert message can lose the host identifier when the host record is missing: host may be null, resulting in "host null" with no hostId. This makes the alert less actionable in exactly the scenarios where DB lookup fails.
        if (!answer.getResult()) {
            HostVO host = _hostDao.findById(hostId);
            String msg = String.format("Unable to attach storage pool %s to host %s", storagePool, host);

            _alertMgr.sendAlert(AlertManager.AlertType.ALERT_TYPE_HOST, storagePool.getDataCenterId(), storagePool.getPodId(), msg, msg);

engine/storage/volume/src/main/java/org/apache/cloudstack/storage/datastore/provider/DefaultHostListener.java:167

  • If hostDao.findById(hostId) returns null, the alert will say "host null" and omit the host id. Keeping a fallback to hostId preserves actionable context during attach failures.
        if (!answer.getResult()) {
            String msg = String.format("Unable to attach storage pool %s to the host %s", pool, host);
            alertMgr.sendAlert(AlertManager.AlertType.ALERT_TYPE_HOST, pool.getDataCenterId(), pool.getPodId(), msg, msg);

server/src/main/java/com/cloud/vm/UserVmManagerImpl.java:7777

  • These alerts now rely on Account.toString() / Domain.toString(). If _accountDao.findById(...) returns null (e.g., stale dedication records), the message becomes "... dedicated to account null ..." and loses the id that previously made the alert actionable. Consider falling back to the id when the entity lookup fails.

This issue also appears on line 7784 of the same file.

                Account srcAccount = _accountDao.findById(srcAccountId);
                Account destAccount = destAccountId != null ? _accountDao.findById(destAccountId) : null;
                String msg = String.format("VM is being migrated from host %s explicitly dedicated to account %s to host %s %s",
                        srcHost, srcAccount, destHost, destAccount != null ? "explicitly dedicated to account " + destAccount : "not dedicated to a specific account");

server/src/main/java/com/cloud/ha/HighAvailabilityManagerImpl.java:525

  • When hostId is null and the host record can't be resolved, the alert body will include host id: null. It would be clearer to omit the id segment or use an explicit "unknown" value when hostId is null.
                } else {
                    hostDesc = "host id: " + hostId;
                }

Copilot AI review requested due to automatic review settings August 15, 2026 11:33

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@apache apache deleted a comment from github-actions Bot Aug 15, 2026
@apache apache deleted a comment from github-actions Bot Aug 15, 2026
@apache apache deleted a comment from github-actions Bot Aug 15, 2026
@apache apache deleted a comment from github-actions Bot Aug 15, 2026
@apache apache deleted a comment from codecov Bot Aug 15, 2026
@codecov

codecov Bot commented Aug 15, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 59.34066% with 37 lines in your changes missing coverage. Please review.
✅ Project coverage is 19.81%. Comparing base (cced071) to head (bcd5b3b).
⚠️ Report is 6 commits behind head on main.

Files with missing lines Patch % Lines
...java/com/cloud/agent/manager/AgentManagerImpl.java 0.00% 9 Missing ⚠️
...torage/datastore/provider/ScaleIOHostListener.java 0.00% 7 Missing ⚠️
.../src/main/java/com/cloud/vm/UserVmManagerImpl.java 76.00% 4 Missing and 2 partials ⚠️
.../cloud/configuration/ConfigurationManagerImpl.java 0.00% 5 Missing ⚠️
...rc/main/java/com/cloud/alert/AlertFormatUtils.java 76.92% 2 Missing and 1 partial ⚠️
...tack/engine/orchestration/NetworkOrchestrator.java 0.00% 2 Missing ⚠️
...atastore/driver/ScaleIOPrimaryDataStoreDriver.java 0.00% 2 Missing ⚠️
...java/com/cloud/ha/HighAvailabilityManagerImpl.java 90.00% 0 Missing and 1 partial ⚠️
...om/cloud/storage/snapshot/SnapshotManagerImpl.java 0.00% 1 Missing ⚠️
...n/java/org/apache/cloudstack/ca/CAManagerImpl.java 0.00% 1 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##               main   #13775      +/-   ##
============================================
+ Coverage     19.64%   19.81%   +0.16%     
- Complexity    19786    19991     +205     
============================================
  Files          6368     6369       +1     
  Lines        574889   575320     +431     
  Branches      70353    70371      +18     
============================================
+ Hits         112957   114004    +1047     
+ Misses       449660   448965     -695     
- Partials      12272    12351      +79     
Flag Coverage Δ
uitests 3.41% <ø> (ø)
unittests 21.10% <59.34%> (+0.17%) ⬆️

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

☔ View full report in Codecov by Harness.
📢 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.

@github-actions

github-actions Bot commented Aug 15, 2026

Copy link
Copy Markdown

🔴 Test Coverage Grade: D — Marginal

Metric Value
Line coverage 24.74%
Branch coverage 18.88%

Grade Scale

Grade Line Coverage Meaning
🟢 A ≥ 80% Excellent - this code sleeps well at night 😴
🟡 B 60-79% Good - almost there, don't stop now 😉
🟠 C 40-59% Acceptable - your code is wearing a seatbelt, but no airbags 😬
🔴 D 20-39% Marginal - boldly shipping where no test has gone before 🖖
⛔ F < 20% Failing - tests? what tests? 🔥

Branch coverage is shown as a secondary signal. Grade is determined by line coverage.
View full Actions run

@apache apache deleted a comment from github-actions Bot Aug 15, 2026
@apache apache deleted a comment from github-actions Bot Aug 15, 2026
@apache apache deleted a comment from github-actions Bot Aug 15, 2026
Copilot AI review requested due to automatic review settings August 15, 2026 15:27

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@sonarqubecloud

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Error messages and Alerts should include contextual and actionable information

3 participants