Skip to content

KVM: live volume migration on Ceph RBD, and between RBD, NFS, SharedMountPoint and local pools - #14426

Draft
weizhouapache wants to merge 9 commits into
apache:mainfrom
weizhouapache:24-ceph-volumes-migrations
Draft

weizhouapache wants to merge 9 commits into
apache:mainfrom
weizhouapache:24-ceph-volumes-migrations

Conversation

@weizhouapache

@weizhouapache weizhouapache commented Oct 16, 2026 •

Copy link
Copy Markdown
Member

Description

migrateVolume with livemigrate=true on KVM was refused for every pair of pools, except for storage with its own handling (StorPool, PowerFlex). The error told the operator to use migrateVirtualMachineWithVolumes, which moves the whole Instance to another host. This PR lets an operator move a single volume of a running Instance, without stopping the Instance and without moving it, between:

  • two Ceph RBD pools;
  • an RBD pool and an NFS, SharedMountPoint or host-local pool, in both directions.

A volume is copied in place only when the Instance's host can reach both pools, which is the case for these pairs. A live migration between two file based pools (NFS, SharedMountPoint, local) is not part of this PR and keeps being refused as before. A volume which is not attached to a running Instance can still be copied between any two of those pools, and a SharedMountPoint pool is now copied directly like the NFS and local ones.

Encrypted volumes can also be migrated between RBD and NFS, online and offline.

How it works:

  • Management server. VolumeApiServiceImpl accepts these pool pairs for a KVM live migration. A local pool has to be the one of the host the Instance is running on, as the copy runs there. Storage answers which pool types are copied in place (isMigrationBetweenRbdOrRbdAndFileBased), so that no caller compares pool types itself. AncientDataMotionStrategy keeps the volume's format right after the move (RAW on RBD, QCOW2 on a file pool) and its encryption format (luks2 on RBD, luks elsewhere), and bypasses secondary storage for a SharedMountPoint pool, as it does for NFS and local ones.
  • KVM agent. LibvirtMigrateVolumeCommandWrapper builds the disk XML of the destination for the type of the destination pool (an RBD image or a qcow2 file) and runs a libvirt block copy on the running domain. The whole disk is copied, so a volume cloned from a template does not depend on a backing file of the source pool. SHALLOW is used only from RBD to RBD. After the pivot the source volume is removed. An encrypted volume gets its destination created with the encryption header first; an offline copy goes through qemu-img with both secrets.
  • After the pivot, a failure is only logged. Once the block copy is pivoted the Instance writes to the destination. The removal of the libvirt secret, and of the source volume, can fail from then on without failing the migration, and the destination volume is never removed, so CloudStack no longer keeps a volume on the source pool while the Instance uses the destination one.
  • The name of a copied volume. An RBD image is named after its UUID only. A volume copied offline to an RBD pool used to be named <uuid>.raw; a later online migration keeps the name of a volume, so the qcow2 file written by the block copy to an NFS pool ended up named .raw, was taken for a raw volume, and the Instance could not start again (qemu was told to open the file as a block device). A volume of a file based pool keeps being named after its format, with the .qcow2 extension.

The branch has nine commits:

  1. utils: add RbdUtils for the Ceph monitors of an RBD pool. This is the first commit of utils,kvm: build every Ceph monitor list with RbdUtils #14402, so the encrypted copy can build its mon_host with RbdUtils.getRbdMonitors. It will drop out of this PR when utils,kvm: build every Ceph monitor list with RbdUtils #14402 is merged.
  2. KVM: live volume migration on ceph. RBD to RBD.
  3. smoke tests: exercise online volume migration for KVM on RBD.
  4. KVM: live migrate volumes between RBD, NFS, SharedMountPoint and local pools. The migration of a volume between RBD and file based pools, encrypted or not, with its unit tests and test_volume_migration_rbd_nfs.py.
  5. KVM: copy a volume of a SharedMountPoint pool directly between primary storages. A SharedMountPoint volume was staged on secondary storage, which does not handle an encrypted volume.
  6. KVM: do not fail a volume migration whose block copy was pivoted.
  7. KVM: leave the format detection of libvirt volumes and the pool refresh out of the migration. A change of the format detection of every libvirt volume is not needed here, and neither is the refresh of the destination pool.
  8. KVM: do not name an RBD volume copied between primary storages after a format.
  9. KVM: limit live volume migration to RBD pools and RBD to file based pools. The block copy between two file based pools is left out for now.

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

How Has This Been Tested?

Unit tests, on this branch: RbdUtilsTest (17), StorageTest (10), VolumeApiServiceImplTest (164), AncientDataMotionStrategyTest (19), LibvirtMigrateVolumeCommandWrapperTest (14), KVMStorageProcessorTest (53) and LibvirtStorageAdaptorTest (23), all passing. All the tests of the com.cloud.hypervisor.kvm (961), org.apache.cloudstack.storage.motion (78) and com.cloud.storage packages pass, and so does a full mvn install of the server module with its upstream modules (4059 tests in server, no failure). New cases cover the pool pairs that are accepted, the local pool of another host, the dispatch of the agent to the block copy, the failures after the pivot, and the name of a volume copied to an RBD pool and to a file based pool.

Live matrices, on the same changes from my 4.23.0-ceph branch, which carries them together with the commits of my other Ceph PRs. Two KVM hosts; Ceph with two pools; two NFS pools; two SharedMountPoint pools; one local pool per host. An Instance with a ROOT and a DATA volume, moved together. After each leg:

  • both volumes are on the expected pool in the API;
  • the checksum of the first 31 KiB of the ROOT disk is unchanged, and a 4 MiB pattern written to the DATA disk before the first move is intact;
  • the SSH port of the Instance answers;
  • then the Instance is stopped and started, and the same four checks are repeated.

Results, from runs made before commit 9: 15 online and 15 offline legs of non-encrypted volumes passed (the online run starts with an offline move to RBD), including RBD to RBD and back, RBD to and from NFS, SharedMountPoint and local, and the moves among the file based pools. Commit 9 came after these runs. It makes the 8 online legs among NFS, SharedMountPoint and local pools refuse, so those no longer apply; the other 7 online legs, which involve RBD, and the 15 offline legs still do. I did not rerun the matrices after commit 9; its refusal is covered by the unit tests and by the smoke test, which asserts it. A run of 10 legs, which copies a volume offline to RBD and then moves it online to a file based pool, passed; that is the sequence which produced the .raw file before commit 8. A 5 GiB DATA disk took about 45 to 95 seconds to copy, a small ROOT disk 3 to 9 seconds.

Encrypted volumes: 10 online legs passed, and the first 6 offline legs passed before I stopped that run (the 5 others were not run). All of them were between NFS, SharedMountPoint and local pools, as the KVM hosts of the lab cannot encrypt an RBD image (see below). The online ones were among file based pools, so they too predate commit 9 and are now refused.

An early run failed once on an RBD to RBD copy of the DATA disk: the copy finished and the Instance switched to the new image, but the removal of the old image by libvirt failed ("failed to remove volume … No such file or directory"), the migration was reported as failed, and CloudStack kept the old pool while the Instance used the new one. I did not find why the removal failed, and it did not happen again; the agent no longer fails a migration for it (commit 6).

Not done:

  • The migration of an encrypted volume from or to an RBD pool was not exercised in the lab: the KVM hosts there run QEMU 6.2, which cannot encrypt an RBD image ("RBD library does not support image encryption"), so an encrypted RBD volume cannot be created and an attempt is refused.
  • The Marvin smoke test test_volume_migration_rbd_nfs.py has not been run by Marvin from this branch (Marvin does not work on that setup).
  • migrateVirtualMachineWithVolumes was not retested.

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

  • The Instance is stopped and started after every move. That is what exposed the .raw name above, because a wrong format on the volume only shows when the Instance starts again.
  • A local pool of a host other than the one the Instance runs on is refused with a clear error. Pool pairs outside the list keep the old error, including a live migration between two file based pools.
  • A destination on a pool over its usage threshold is refused by the existing capacity check, as before.
  • An encrypted volume is moved offline between a SharedMountPoint pool and the others, which failed with "Parameter 'encrypt.key-secret' is required for cipher" before commit 5.
  • This branch is based on apache/main, which does not yet have kvm: look RBD volumes up through librbd instead of refreshing the whole pool #14188 or kvm: remove the partial RBD image when a template copy fails #14393. Two edits of this work to mon_host lines in methods from those PRs were left out, so expect a small conflict in LibvirtStorageAdaptor when they merge.

Everything that talks to Ceph needs the pool's monitors as a list the client
can parse, and the rules are the same wherever that list is built: give each
monitor the pool's port unless it names one already, and put a bare IPv6
address in square brackets so its own colons stay distinguishable from the
separator before the port.

The mon_host option of a disk's rbd: string wants the same list again, with
':' and ';' escaped, because those two separate the options of that string and
its monitors.

None of it depends on a storage pool, so collect it in RbdUtils as static
methods with their unit tests, rather than leaving each caller to grow a copy
that is right in a different set of cases.
- enable migrate volume between ceph
- regenerate disk xml for virsh blockcopy
- use SHALLOW flag instead of REUSE_EXT
test_13_migrate_volume_and_change_offering previously always stopped
the VM before migrating an attached volume on KVM. Now that
VolumeApiServiceImpl allows KVM to live-migrate a volume between two
RBD pools (VolumeApiServiceImpl.isSourceAndDestOnRBD), keep the VM
running and pass livemigrate=true for that RBD-to-RBD case, same as
already done for VMware/XenServer. Any other KVM source/destination
combination keeps the existing stop/migrate/start behavior.
…l pools

Migrate a volume of a running Instance between an RBD pool and an NFS,
SharedMountPoint or host-local pool, and between those file based pools, with
a libvirt block copy on the host the Instance runs on, so that neither the
Instance nor its host change. Migrate encrypted volumes between RBD and NFS,
online and offline.

Management server:
- VolumeApiServiceImpl lets a KVM live migration through for these pool pairs,
  where it asked for migrateVirtualMachineWithVolumes before. A local pool has
  to be the one of the host the Instance runs on.
- AncientDataMotionStrategy keeps the format of the volume right after the
  move: RAW on RBD, QCOW2 on a file based pool, and luks2 or luks as the
  encryption format, as the agent encrypts an RBD volume with librbd and any
  other volume with qemu.

KVM agent:
- LibvirtMigrateVolumeCommandWrapper builds the disk XML of the destination
  for the type of the destination pool, an RBD image or a qcow2 file, and
  copies the whole disk, so a volume cloned from a template does not depend on
  a backing file of the source pool. SHALLOW is only used from RBD to RBD. The
  source volume is removed after the pivot and the destination pool refreshed.
- An encrypted volume gets its destination created with the encryption header
  first, and an offline copy goes through qemu-img with both secrets
  (LibvirtStorageAdaptor, KVMStorageProcessor).
- LibvirtStorageVolumeXMLParser read the volume format with its arguments
  swapped and found none, so a migrated qcow2 file named like an RBD image was
  taken for a raw one and the Instance failed to start again. It reads the
  format of the volume now.
- The ceph.conf which the copy of an encrypted volume writes gets its mon_host
  from RbdUtils.getRbdMonitors, which gives each monitor its port, leaves
  alone one which has it, and brackets a bare IPv6 address.

Tests:
- Unit tests for the pool pairs which are accepted, the local pool of another
  host, and the dispatch of the agent to the block copy.
- test_volume_migration_rbd_nfs.py migrates ROOT and DATA volumes online,
  offline and detached, encrypted or not, and stops and starts the Instance
  after every move to check that it is still reachable.
- test_volumes.py: the data disk of the encrypted volume migration test is
  found by its size.
@codecov

codecov Bot commented Oct 16, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 48.44125% with 215 lines in your changes missing coverage. Please review.
✅ Project coverage is 20.42%. Comparing base (d3f0700) to head (3a1a22c).

Files with missing lines Patch % Lines
...ce/wrapper/LibvirtMigrateVolumeCommandWrapper.java 59.07% 80 Missing and 26 partials ⚠️
.../hypervisor/kvm/storage/LibvirtStorageAdaptor.java 1.38% 71 Missing ⚠️
...tack/storage/motion/AncientDataMotionStrategy.java 0.00% 9 Missing ⚠️
...n/java/com/cloud/storage/VolumeApiServiceImpl.java 50.00% 3 Missing and 5 partials ⚠️
.../cloud/agent/api/storage/MigrateVolumeCommand.java 0.00% 6 Missing ⚠️
...oud/hypervisor/kvm/storage/LibvirtStoragePool.java 0.00% 6 Missing ⚠️
...m/cloud/hypervisor/kvm/storage/KVMStoragePool.java 0.00% 3 Missing ⚠️
utils/src/main/java/com/cloud/utils/RbdUtils.java 89.28% 2 Missing and 1 partial ⚠️
api/src/main/java/com/cloud/storage/Storage.java 93.33% 0 Missing and 1 partial ⚠️
...tack/storage/endpoint/DefaultEndPointSelector.java 0.00% 1 Missing ⚠️
... and 1 more
Additional details and impacted files
@@             Coverage Diff              @@
##               main   #14426      +/-   ##
============================================
+ Coverage     20.39%   20.42%   +0.02%     
- Complexity    21283    21335      +52     
============================================
  Files          6481     6482       +1     
  Lines        588040   588448     +408     
  Branches      72021    72109      +88     
============================================
+ Hits         119957   120177     +220     
- Misses       455052   455208     +156     
- Partials      13031    13063      +32     
Flag Coverage Δ
uitests 3.70% <ø> (ø)
unittests 21.72% <48.44%> (+0.02%) ⬆️

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.

@winterhazel
winterhazel self-requested a review October 16, 2026 16:29
@bernardodemarco
bernardodemarco self-requested a review October 16, 2026 16:29
@weizhouapache

weizhouapache commented Oct 16, 2026 •

Copy link
Copy Markdown
Member Author

@winterhazel @bernardodemarco
thanks for the interest and self-assignment.

I will revert some of the changes related to live volume migration between NFS, local, and SharedMountPoint pools. These changes use blockcopy for the migrations. Although they worked in my testing, I think it's better to keep the current behavior and leave this out of the scope of the PR for now. We can discuss it separately later.

@wido

wido commented Oct 16, 2026

Copy link
Copy Markdown
Contributor

This is really great! Let me review this soon

@wido wido 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.

Went through this by hand first and then had Claude Fable dig through the paths I wasn't sure about. Really great work, we've wanted this for years!

One thing I think is blocking: in migrateRBDVolume everything after the pivot can still fail the migration. The delete of the source volume in the finally isn't guarded and pool.refresh() is inside the try. If one of those throws the agent reports a failure, mgmt server keeps the volume on the old pool, but qemu is already writing to the new image. Next stop/start the instance boots from the old image or doesn't start at all. Thats your 5th run failure I think. Once the PIVOT returned the migration is done, delete and refresh should just log and not touch the answer anymore. Was the source image still there after that failed run btw?

The LibvirtStorageVolumeXMLParser fix is correct (args were swapped) but it changes format detection for every volume on every libvirt pool, that fallback has been in effect since forever. I'd put that in a seperate PR with its own testing. LXC .tar templates for example get probed as raw now.

Agree with dropping NFS/SMP/local live migration from this PR. The server gate, isFileBasedPool in the wrapper, smoke tests and the migrateRBDVolume name should then go together.

Checked and fine: the encrypted copy in copyPhysicalDisk is only reached from the primary to primary copy with both passphrases set, templates and snapshots are not affected. Endpoint selector change only hits running instances.

Ran the unit tests from the description on the branch with JDK 17, 238 tests, all pass.

I don't have a Ceph test env at the moment. CCC is coming up in November, can you give me a demo there so we can verify this together? Would love to see it live.

@weizhouapache

Copy link
Copy Markdown
Member Author

thanks a lot @wido !

I will address the first issue.

the 2nd issue is one of my major concerns too. the fix is small but it could have large impact. I will research

…y storages

A volume which is not live migrated is copied directly between two pools, with
qemu-img and its passphrase, only if the data motion strategy can bypass
secondary storage for both pools. A SharedMountPoint pool was left out of the
pool types it bypasses it for, although it is a file based pool like the
NetworkFilesystem and Filesystem ones: its volume was staged on secondary
storage, and the copy to and from secondary storage does not handle an
encrypted volume, so qemu-img failed with "Parameter 'encrypt.key-secret' is
required for cipher" after the migration had been accepted.

Bypass secondary storage for a SharedMountPoint pool as well, which the agent
already supports: it copies a volume between two file based pools in place, and
an encrypted one with its passphrase.
Once the block copy of a running Instance is pivoted, the Instance writes to the
destination volume. migrateRBDVolume still let what follows fail the migration:
the removal of the source volume in the finally block was not guarded, the
refresh of the destination pool was inside the try, and so was the removal of
the libvirt secret of the source volume in checkBlockJobStatus. A failure of one
of them made the agent report a failed migration, so the management server kept
the volume on the source pool while the Instance used the destination one, and
the Instance would start from the source volume, or not start, the next time.
For an encrypted volume the destination volume was even removed as that of a
failed migration.

Remember that the block copy was pivoted, and from then on only log the failure
to remove the secret, to refresh the pool or to remove the source volume, and
never remove the destination volume.
…sh out of the migration

The volume format read by LibvirtStorageVolumeXMLParser changes how
getPhysicalDisk picks the format of every volume of every libvirt pool, not
only of a migrated one: libvirt probes the content of a file, so a tar template
is reported as raw instead of tar, and a raw volume without a suffix is raw
instead of the QCOW2 default. That is a change of its own, with its own
testing, so go back to the parser it had.

The migration does not need it. A volume migrated to a file based pool is named
after the format of the destination, so the suffix of its name matches its
content, and the refresh of the destination pool after the block copy is not
needed either: getVolume refreshes the pool when it does not find a volume that
was written outside of libvirt.

Drop the refresh of the pool, and its test.
…a format

copyVolumeFromPrimaryToPrimary named the destination volume <uuid>.<extension
of the default format of the destination pool>: <uuid>.raw on an RBD pool and
<uuid>.qcow2 on a file based one. The name of an RBD image is not read, but a
volume keeps its name when it is migrated online to another pool, where the
libvirt block copy writes a qcow2 file under it. A volume copied offline to an
RBD pool, and then migrated online to a file based pool, ended up as a qcow2
file named <uuid>.raw. getPhysicalDisk takes a name ending with ".raw" for a raw
volume, so the Instance could not be started again: qemu was told to open the
file as a block device.

Name the volume of an RBD pool after its UUID only. The volume of a file based
pool is still named after its format, with the ".qcow2" extension.
…ools

Revert the block copy between NFS, SharedMountPoint and host-local pools for
now. A volume of a running Instance is copied in place only between two RBD
pools, or between an RBD pool and a file based pool (NFS, SharedMountPoint or
local), as both pools are then reachable from the host the Instance runs on.

Storage answers which pools those are, so that neither caller compares the pool
types itself: arePoolsSameType and isAnyPoolFileBased compare two pool types,
areBothPoolsFileBased tells two file based pools apart from the rest, and
isCopiedInPlaceOnKvm composes the combinations a libvirt block copy reaches.
VolumeApiServiceImpl asks it in the live migration check and in the encrypted
volume check, LibvirtMigrateVolumeCommandWrapper asks it to choose between a
block copy and a copy with qemu-img, and AncientDataMotionStrategy uses the set
of file based pool types it keeps.

The tests of test_volume_migration_rbd_nfs.py which hop between two file based
pools assert the refusal instead of the move: a volume attached to a running
Instance is answered by the live migration check whatever the livemigrate flag
says, and a detached encrypted volume by the encrypted volume check. An offline
hop of a plain volume between two file based pools is still allowed, and is
still made.
@weizhouapache

Copy link
Copy Markdown
Member Author

Went through this by hand first and then had Claude Fable dig through the paths I wasn't sure about. Really great work, we've wanted this for years!

One thing I think is blocking: in migrateRBDVolume everything after the pivot can still fail the migration. The delete of the source volume in the finally isn't guarded and pool.refresh() is inside the try. If one of those throws the agent reports a failure, mgmt server keeps the volume on the old pool, but qemu is already writing to the new image. Next stop/start the instance boots from the old image or doesn't start at all. Thats your 5th run failure I think. Once the PIVOT returned the migration is done, delete and refresh should just log and not touch the answer anymore. Was the source image still there after that failed run btw?

addressed in abdaa03

The LibvirtStorageVolumeXMLParser fix is correct (args were swapped) but it changes format detection for every volume on every libvirt pool, that fallback has been in effect since forever. I'd put that in a seperate PR with its own testing. LXC .tar templates for example get probed as raw now.

reverted in dac5d81
and fixed an issue in NFS->RBD->NFS migration: c8b302d

Agree with dropping NFS/SMP/local live migration from this PR. The server gate, isFileBasedPool in the wrapper, smoke tests and the migrateRBDVolume name should then go together.

addressed in 3a1a22c

Checked and fine: the encrypted copy in copyPhysicalDisk is only reached from the primary to primary copy with both passphrases set, templates and snapshots are not affected. Endpoint selector change only hits running instances.

Ran the unit tests from the description on the branch with JDK 17, 238 tests, all pass.

I don't have a Ceph test env at the moment. CCC is coming up in November, can you give me a demo there so we can verify this together? Would love to see it live.

@weizhouapache

weizhouapache commented Oct 19, 2026 •

Copy link
Copy Markdown
Member Author

I don't have a Ceph test env at the moment. CCC is coming up in November, can you give me a demo there so we can verify this together? Would love to see it live.

sure @wido

Actually many cases are covered by a smoke test introduced in this PR: test_volume_migration_rbd_nfs.py

Coverage

14 tests in two classes: TestVolumeMigrationRbdNfs and
TestEncryptedVolumeMigrationRbdNfs run the same seven scenarios, the second
one with encrypted ROOT and DATA volumes.

# Scenario Plain volumes Encrypted volumes
01 Online: RBD (ROOT with chain) -> NFS -> NFS -> RBD -> RBD NFS -> NFS refused, the rest made same
02 Online: NFS (ROOT with chain) -> RBD made same
03 Online: NFS -> NFS refused same
04 Offline: RBD (ROOT with chain) -> NFS -> NFS -> RBD -> RBD all hops made NFS -> NFS refused, the rest made
05 Offline: NFS (ROOT with chain) -> RBD made same
06 Offline: NFS (ROOT with chain) -> NFS made refused
07 Detached DATA volume: RBD -> NFS -> NFS -> RBD -> RBD all hops made NFS -> NFS refused, the rest made

A refused hop asserts the message of the check that answers it, the live
migration one or the encrypted volume one, rather than any failure.

What is verified after every migration

Every hop is verified twice: right after the migration, and once more after the
Instance has been stopped and started again, so that a volume which is still
open in the running domain but is no longer usable from its recorded format is
caught as well.

  • the volume is on the destination pool and is Ready, and the Instance is
    Running
  • the pattern written to the DATA volume before the first migration is still
    readable at the same offset, and the checksum of the boot area of the ROOT
    volume is unchanged. Both are read through the disk of the running domain, as
    the Instance sees them, so an encrypted volume is read decrypted and through
    qemu rather than as a file on the pool
  • for an encrypted volume, the disk in the XML domain still carries its
    encryption, with the scheme of the destination: luks2 with the librbd
    engine on an RBD pool, luks with another engine on a file based one

Test results

Run on a nested Trillian environment: KVM, two management servers, two hosts,
two permanent RBD (Ceph) primary pools, and the NFS pools the suite creates
itself.

On the current branch tip:

Test Result
test_volume_migration_rbd_nfs.py 14/14 OK (Ran 14 tests in 7461.509s)
test_volumes.py TestVolumeEncryption.test_04_encrypted_volume_migration_between_rbd_pools 1/1 OK (Ran 1 test in 1056.071s)

@weizhouapache

Copy link
Copy Markdown
Member Author

@blueorangutan package

@blueorangutan

Copy link
Copy Markdown

@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.

@blueorangutan

Copy link
Copy Markdown

Packaging result [SF]: ✔️ el8 ✔️ el9 ✔️ el10 ✔️ debian ✔️ suse15. SL-JID 19608

This branch has not been deployed

No deployments
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.

3 participants