GeezerVisonThe World Wide Web, restored to 800 pixels of glory. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Home|About|Gaming cabinet|Archives|How it works|Starter sites | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
GeezerVison is showing github.com — kvm: support Host HA on Ceph RBD primary storage by weizhouapache · Pull Request #14320 · apache/cloudstack Conversation
Member
DescriptionExtend the existing KVM Host-HA heartbeat/VM-activity-check framework (currently limited to NetworkFilesystem and SharedMountPoint pools) to also cover RBD primary storage, based on the approach from the old PR #5862, adapted to the current HA architecture and reusing the multi-monitor Ceph support already added in #6792.
Types of changes
Feature/Enhancement Scale or Bug SeverityFeature/Enhancement Scale
Bug Severity
Screenshots (if appropriate):How Has This Been Tested?How did you try to break this feature and the system with this change?
Sorry, something went wrong. Uh oh!
There was an error while loading. Please reload this page. All reactions
Extend the existing KVM Host-HA heartbeat/VM-activity-check framework (currently limited to NetworkFilesystem and SharedMountPoint pools) to also cover RBD primary storage, based on the approach from the old PR apache#5862, adapted to the current HA architecture and reusing the multi-monitor Ceph support already added in apache#6792. - Add StoragePoolType.RBD to LIBVIRT_STORAGE_POOL_TYPES_WITH_HA_SUPPORT, which is the single switch that makes pool registration, KVMHAMonitor, and the CheckOnHostCommand/CheckVMActivityOnStoragePoolCommand wrappers treat RBD pools as HA-capable. - LibvirtStoragePool: build rbd/rados connection args (--mon-host, pool, and cephx --id/--key when set) from the pool's existing sourceHost/ sourceDir/authUsername/authSecret fields for the heartbeat and VM-activity checks, mirroring the conventions KVMPhysicalDisk already uses to talk to RBD. - Add kvmheartbeat_rbd.sh and kvmvmactivity_rbd.sh: RBD has no shared mount point to write a heartbeat file to, so the heartbeat timestamp is stored as a small RADOS object per host instead, and VM activity is detected via RBD watchers (rbd status) rather than file mtimes. - Minor: fix a stale "NFS storage pool" log message in KVMHAMonitor now that this path also runs for RBD. - Add LibvirtStoragePoolTest#testIsPoolSupportHA covering the new RBD case (no HA/heartbeat tests existed previously for any pool type).
3 of 14 tasks
|
There was an error while loading. Please reload this page.
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@ ## main #14320 +/- ## ============================================ + Coverage 20.75% 20.83% +0.07% - Complexity 21901 22016 +115 ============================================ Files 6496 6497 +1 Lines 591602 591962 +360 Branches 72583 72638 +55 ============================================ + Hits 122814 123318 +504 + Misses 455456 455272 -184 - Partials 13332 13372 +40
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
@blueorangutan package |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
@weizhouapache a [SL] Jenkins job has been kicked to build packages. It will be bundled with no SystemVM templates. I'll keep you posted as I make progress. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
Packaging result [SF]: ✔️ el8 ✔️ el9 ✔️ el10 ✔️ debian ✔️ suse15. SL-JID 19426 |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
@blueorangutan test |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
@weizhouapache a [SL] Trillian-Jenkins test job (ol8 mgmt + kvm-ol8) has been kicked to run smoke tests |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
[SF] Trillian test result (tid-17079)
|
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Critical RBD monitor-port and stale-heartbeat handling issues remain, along with incomplete HA cleanup.
Extends KVM Host HA heartbeat and VM-activity checks to Ceph RBD primary storage.
Changes:
| File | Summary |
|---|---|
scripts/vm/hypervisor/kvm/kvmvmactivity_rbd.sh |
Adds RBD watcher-based VM activity detection. |
scripts/vm/hypervisor/kvm/kvmheartbeat_rbd.sh |
Adds RADOS-backed heartbeat handling; stale delays over 255 seconds require bounded status handling. |
plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/storage/LibvirtStoragePoolTest.java |
Tests RBD HA support eligibility. |
plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/LibvirtStoragePool.java |
Selects RBD scripts and builds Ceph arguments; monitor ports must be propagated, and missing-script errors should be generic. |
plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/KVMHAMonitor.java |
Generalizes the storage-pool log message. |
engine/components-api/src/main/java/com/cloud/ha/HighAvailabilityManager.java |
Enables RBD HA support; corresponding pool deletion paths must also clean up HA state. |
🧠 Review effort: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
- pass the pool's monitor port to the RBD heartbeat/activity scripts, for every monitor, instead of relying on the default port - kvmheartbeat_rbd.sh: keep the heartbeat age out of the function return status, which wraps above 255 and made a long-stale heartbeat look ALIVE - remove pools from the HA monitor on deletion for all storage pool types with HA support, without trying to umount an empty mount path - make the missing-script error message generic - add unit tests for the RBD monitor list (IPv4, IPv6, mixed, with/without port)
|
@blueorangutan package |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
@weizhouapache a [SL] Jenkins job has been kicked to build packages. It will be bundled with no SystemVM templates. I'll keep you posted as I make progress. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Warning
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.
kvmheartbeat_rbd.sh uses -h to derive the per-host RADOS object name… · New-h was provided; if HostIP is empty, the heartbeat object… · Newpool.getMountDestPath() directly into a shell command string can break if the path… · NewsourcePort <= 0, this returns sourceHost without normalization. If sourceHost contains… · NewauthUsername != null is not sufficient to safely add cephx args: authUsername could be… · New-t help text says 'time on ms', but the caller (LibvirtStoragePool) passes seconds… · New-t help text says 'time on ms', but the caller (LibvirtStoragePool) passes seconds… · New-t help text says 'time on ms', but the caller (LibvirtStoragePool) passes seconds… · New🧠 Review effort: Lite
Give feedback about Copilot approvals in this survey to enter a drawing for a $150 gift card.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
|
Packaging result [SF]: ✔️ el8 ✔️ el9 ✔️ el10 ✔️ debian ✔️ suse15. SL-JID 19467 |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
…of the pool Follow-up to the review of the Host HA on Ceph RBD support: - kvmheartbeat_rbd.sh and kvmvmactivity_rbd.sh: exit with an error when the host IP, which names the RADOS objects, is missing (the self-fencing -c of the heartbeat script does not need it), or when a Ceph user is given without its key - LibvirtStoragePool: trim the Ceph monitors and skip empty entries, with or without a port; pass the Ceph user and key only if both are set and fail with a clear error if only one of them is - KVMHAMonitor: run umount without a shell when removing a pool - kvmvmactivity_rbd.sh: fix the -t help text and drop the unused field from the stored activity state - add unit tests for the monitor list (multiple IPv4 and IPv6 monitors, with and without a port, with spaces) and for the Ceph user and key handling
|
@blueorangutan package |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Warning
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.
: as an IPv6 literal and will wrap it in brackets, which… · NewgetRbdMonitors() currently branches on the presence of : (which can also appear in… · New--key exposes it in the process list (both for this script’s args and… · Newinterval is used in a numeric comparison but is never validated when running with -r. If -r… · New${UUIDList//,/ } expansion relies on shell word-splitting and can mis-handle… · Newrados ... stat output content to detect existence is brittle (output formats can vary, and… · New-h was provided; if HostIP is empty, the heartbeat object…kvmheartbeat_rbd.sh uses -h to derive the per-host RADOS object name…-t help text says 'time on ms', but the caller (LibvirtStoragePool) passes seconds…-t help text says 'time on ms', but the caller (LibvirtStoragePool) passes seconds…-t help text says 'time on ms', but the caller (LibvirtStoragePool) passes seconds…authUsername != null is not sufficient to safely add cephx args: authUsername could be…sourcePort <= 0, this returns sourceHost without normalization. If sourceHost contains…pool.getMountDestPath() directly into a shell command string can break if the path…🧠 Review effort: Lite
Give feedback about Copilot approvals in this survey to enter a drawing for a $150 gift card.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
…st HA checks, and harden the parsing Follow-up to the review of the Host HA on Ceph RBD support: - LibvirtStoragePool: do not add a port to Ceph monitors which have one already, and only wrap bare IPv6 addresses in square brackets; mask the Ceph key in the logged command - kvmheartbeat_rbd.sh, kvmvmactivity_rbd.sh: give the Ceph key to rados and rbd in a temporary keyfile instead of --key - kvmheartbeat_rbd.sh: require -t to be a number when checking a heartbeat - kvmvmactivity_rbd.sh: read the list of volumes without word splitting or globbing, skipping empty entries, and check if the activity object exists by the exit status of rados stat - add unit tests for monitors with a port and for the masked key
…installed in the RBD HA scripts The packages python3-rados and python3-rbd are only suggested by the agent packages, so the scripts check at the start that they can be imported, and say which package is missing: - the heartbeat is not written (exit 1), with the reason - the heartbeat check and the VM activity check are inconclusive (exit 2, no DEAD), so the host is not considered dead The self-fencing (-c) does not use Ceph, so it does not need them.
…os and librbd python3-rados and python3-rbd are in the repository of Ceph, which is not configured on every host, so the agent could not be installed on EL8 without it, even without Ceph storage. The scripts of the Host HA on RBD check that they are installed.
|
@blueorangutan package |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
@weizhouapache a [SL] Jenkins job has been kicked to build packages. It will be bundled with no SystemVM templates. I'll keep you posted as I make progress. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
Packaging result [SF]: ✔️ el8 ✔️ el9 ✔️ el10 ✔️ debian ✔️ suse15. SL-JID 19773 |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
[SF] Trillian test result (tid-151)
|
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
This pull request has merge conflicts. Dear author, please fix the conflicts and sync your branch with the base branch. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
…e test PRs Add the commits for apache#14386, apache#14320 and apache#11931 and update the notes.
|
@blueorangutan package |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
@weizhouapache a [SL] Jenkins job has been kicked to build packages. It will be bundled with no SystemVM templates. I'll keep you posted as I make progress. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
Packaging result [SF]: ✔️ el8 ✔️ el9 ✔️ el10 ✔️ debian ✔️ suse15. SL-JID 19851 |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
[SF] Trillian test result (tid-168)
|
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Thanks for working on this. RBD-only deployments really need it. I read it closely because we'd like to run it on our RBD-only KVM cluster. I've sorted the findings by severity.
The main concern is that, as it stands, a host that is still running can be declared Down. Ceph's exclusive lock and blocklisting protect the data, but the running VM loses its disk and is restarted elsewhere.
kvmvmactivity_rbd.py is only reached through KVMHAProvider.isActive, which is Host HA and needs OOBM.LIBVIRT_STORAGE_POOL_TYPES_WITH_HA_SUPPORT turns on the VM-HA path: KVMInvestigator → CheckOnHostCommand → KVMHAChecker → hasHeartBeat. That path uses only the heartbeat age. VM I/O is never consulted before a restart.kvmheartbeat_rbd.py check()). An agent that never wrote one is declared dead:
KVMHAChecker.hasHeartBeat() starts at false, so an empty pool list (any not-yet-upgraded agent) answers alive=false.
storageSupportsHA was false.guid + - + name.HostTO.getGuid(), i.e. AgentShell.getGuid(), which prefers the command line and is a random UUID in dev mode.KVMHA-hb-null-LibvirtComputingResource, shared by every such host.createHeartBeatCommand can now throw:
getRbdMonitors on a null host;KVMHAMonitor.run() catches nothing, so the thread dies and NFS/SMP heartbeats stop too. The host then looks dead.KVMHAChecker the loop overwrites the result per pool, so the verdict comes from the last pool in HashMap order. With mixed NFS and RBD pools, a missing RBD object can outvote a fresh NFS heartbeat.KVMStoragePoolManager.deleteStoragePool(type, uuid, details) now sends RBD (and SMP) to adaptor.deleteStoragePool(uuid). Before, it went to the details variant, which LibvirtStorageAdaptor leaves as the default no-op.removeHeartbeatForHostsFromPool during pool maintenance, while VMs still use it.details delete and only add the HA unregister.haStoragePools lock delay NFS heartbeats as well.kvmvmactivity_rbd.py hard-codes 61 s for "fresh", ignoring kvm.heartbeat.update.frequency (the heartbeat script gets -t).RbdUtils.composeOptionForMonHosts has no caller and duplicates KVMPhysicalDisk.composeOptionForMonHosts.LibvirtCheckVMActivityOnStoragePoolCommandWrapperTest lacks the ASF header.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
@bhouse-nexthop |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
- Report "cannot tell" instead of dead when the RADOS heartbeat object is missing or malformed, or when the neighbour monitors no HA pool - Decide the verdict over all pools instead of the last one - Keep the HA monitor thread alive when a pool cannot run its heartbeat - Do not monitor an RBD pool whose Ceph Python bindings are missing - Share the heartbeat freshness rule (interval plus slack) between scripts - Keep deleting RBD and SharedMountPoint pools with their details - Move the RBD specific decisions into the storage pool
There was an error while loading. Please reload this page.
@bhouse-nexthop
New tests cover I also ran this on a nested environment with KVM hosts and Ceph RBD primary storage. The 9 tests in |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the quick and thorough turnaround, and for the point-by-point reply. I went through fe48966 against each item and ran the unit tests for the changed code. Nearly everything is resolved. One fix from the reply isn't in the code, though, and its new tests fail.
kvmheartbeat_rbd.py now exits 2 for a missing or malformed object. It reports DEAD only when the object exists and is stale.KVMHAChecker returns "alive / can't tell" for an empty pool list, and the old test expectation is updated.guid that host.guid is built from. With the fix for 2, a mismatched GUID now reads as "unable to tell", not DEAD, so the dangerous half of this item is gone.executePoolHeartBeatCommand, run() survives unexpected errors, and KVMHAMonitorTest covers both.KVMHACheckerTest covers it.heartbeat_max_age(), and the activity script gets the real interval through -i. I left one small suggestion inline.getHeartBeatHostId, getVmActivityCheckPath and getHeartBeatPrerequisiteError now live on the pool. Neither the monitor nor the wrapper tests for RBD any more.KVMHAChecker, and it matches NFS. I'm fine with handling it in a follow-up. Please also say it in the PR description or the cwiki page, since RBD-only users without OOBM will rely on that path.Suggests. The EL8 argument holds. The --check-bindings gate at registration fails clearly, and I checked that it exits 1 with a clear message when the bindings are missing. One consequence is worth documenting. A host without the bindings (or with a python3-rbd too old for watchers_list) monitors no RBD pool, so as a neighbour it answers "alive" for any host it checks. KVMHostActivityChecker.checkHostStatusWithNeighbourHosts returns on the first "alive" answer, so on an RBD-only cluster that one host stops VM HA from marking any host Down. This fails safe, so it isn't blocking, but the only signal is one line in that host's agent log. I left an optional follow-up idea inline.composeOptionForMonHosts. Fine, since #14402 adds the callers.KVMStoragePoolManager.deleteStoragePool(type, uuid, details) still sends every HA-capable type, now including RBD and SharedMountPoint, to adaptor.deleteStoragePool(uuid). fe48966 doesn't touch that method. The new KVMStoragePoolManagerTest expects the intended behaviour, and 2 of its 5 tests fail against the current code (details inline). It looks like a hunk got lost in the push.kvmheartbeat_rbd.sh / kvmvmactivity_rbd.sh, rbd status and passing --id/--key on the command line. It would help reviewers to refresh it for the Python/librados scripts, the key in CEPH_KEY, the GUID-named objects, and the Suggests + --check-bindings behaviour.Unit tests I ran on fe48966: KVMHACheckerTest (7), KVMHAMonitorTest (4), LibvirtCheckVMActivityOnStoragePoolCommandWrapperTest (6), LibvirtStoragePoolTest (29), LibvirtComputingResourceTest (323) and RbdUtilsTest (17) all pass. KVMStoragePoolManagerTest has 2 failures out of 5: testPoolsAreDeletedWithDetailsAsBefore and testPoolsWithHaSupportAreRemovedFromTheMonitorWhenDeleted.
Once 7 and its tests are fixed, I'm happy to approve.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
| // this host monitors no storage pool, e.g. its agent is not upgraded yet and does not monitor the pools of the type | ||
| // which a newer version does: it has nothing to tell about the host, which is not a dead host | ||
| logger.debug("KVMHAChecker has no storage pool to check the heart beat for {}, so it can not tell whether the host is alive.", hostAndPools); | ||
| return true; |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Optional follow-up, not blocking. true here becomes CheckOnHostAnswer.isAlive(), and KVMHostActivityChecker.checkHostStatusWithNeighbourHosts returns Up on the first such answer. So one neighbour that monitors no pool (for example, the one RBD host without the bindings) stops every host in the cluster from being marked Down through VM HA. That is the safe direction. CheckOnHostAnswer already has a determined flag, though. Answering "undetermined" here, and having the activity checker skip undetermined answers and ask the next neighbour, would let the other hosts still decide.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
Only the removal from the HA monitor depends on the pool types with HA support. The delete itself stays as it was: only NFS uses the delete without the details, which unmounts the pool. The other types keep the delete which takes the details, so that the libvirt pool, which VMs may still use, is not destroyed.
…ts take A write of the heartbeat which starts on time can take long when Ceph is slow: connecting and writing take up to 30 seconds each. The agent stops a write after heartbeat.update.timeout, so a heartbeat of a host which is alive can be older than the interval by that time. The agent gives heartbeat.update.timeout to the heartbeat and the VM activity scripts of RBD with -w, and a heartbeat is stale when it is older than the interval plus that time. Without -w the scripts use 60 seconds, the default of the property.
|
@blueorangutan package |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
@weizhouapache a [SL] Jenkins job has been kicked to build packages. It will be bundled with no SystemVM templates. I'll keep you posted as I make progress. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
Packaging result [SF]: ✔️ el8 ✔️ el9 ✔️ el10 ✔️ debian ✔️ suse15. SL-JID 19980 |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
@blueorangutan test |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
@RosiKyu a [SL] Trillian-Jenkins test job (ol8 mgmt + kvm-ol8) has been kicked to run smoke tests |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
[SF] Trillian test result (tid-211)
|
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
[SF] Trillian test result (tid-17555)
|
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
Successfully merging this pull request may close these issues.
[Status] KVM Host-HA using CEPH RBD
There was an error while loading. Please reload this page.