Skip to content

server: Avoid device id conflicts between data volumes, the CD-ROM and the config drive ISO - #14073

Open
weizhouapache wants to merge 5 commits into
apache:4.22from
shapeblue:4.22-fix-13484
Open

weizhouapache wants to merge 5 commits into
apache:4.22from
shapeblue:4.22-fix-13484

Conversation

@weizhouapache

@weizhouapache weizhouapache commented Sep 7, 2026 •

Copy link
Copy Markdown
Member

Description

This PR fixes #13484 (the fix for main, which also covers multiple ISOs per Instance (#14321), is in #14407).

On KVM, a data volume could get the same device id as the CD-ROM or the config drive ISO. When both devices end up with the same sd* target name (SATA CD-ROMs on UEFI/q35 Instances plus SCSI or SATA data disks), libvirt rejects the domain XML with target 'sde' duplicated for disk sources .... The config drive ISO is attached with the device id 4, but the allocators of volume device ids only reserved the device id 3 (the CD-ROM), so the third data volume got the device id 4.

The same conflict could happen when attaching a volume to a stopped Instance (it is accepted, and the Instance cannot start any more), when restoring volumes/Instances from backup, and when importing Instances (unmanaged Instances and VMware to KVM), which numbered the data disks 1, 2, 3, 4, ...

Device ids of an Instance

Device Device id
Root volume 0
CD-ROM (ISO) 3
Config drive ISO (if the Instance uses config drive) 4
Data volumes 1, 2, then the next device ids which are not used by the CD-ROM and the config drive. The maximum number of data volumes is not reduced by the reserved device ids.

Example (default maximum of 6 data volumes):

Config drive Reserved device ids Data volumes
no 3 1, 2, 4, 5, 6, 7
yes 3, 4 1, 2, 5, 6, 7, 8

An Instance uses config drive if the Dhcp, Dns or UserData service of any of its networks is provided by ConfigDrive (checked on the network providers, so it also works for Instances which have never been started), or if it has the config drive location detail.

Only one ISO can be attached to an Instance in this version, so there is a single CD-ROM (device id 3), and the config drive ISO is one more CD-ROM. The implementation is the same as in #14407, where the number of CD-ROMs is calculated from the host and the attached ISOs instead of being 1, so that the logic can be merged forward to main.

Changes

  • TemplateManager.getCdromDeviceIds(vm) returns the device ids of the CD-ROM devices of an Instance, starting from CDROM_PRIMARY_DEVICE_SEQ (3): the CD-ROM, and the config drive ISO (device id 4) if the Instance uses config drive. getCdromDeviceIds(vm, configDriveUsed) does the same with the specified usage of config drive, for the cases where the networks of the Instance are not known yet. The detection of config drive is in TemplateManagerImpl.
  • VolumeApiService.getReservedDeviceIds(vm) (and the variant with configDriveUsed) returns these device ids. It is used when allocating device ids in:
    • attach volume (auto-allocated device ids, and validation of the deviceid parameter, whose error message now lists the reserved ids). This also covers Instances which are stopped.
    • restore of volumes and Instances from backup (KVMGuru). When a whole Instance is restored, its networks may not be available any more, so the device id of the config drive is always kept free.
    • import of Instances (unmanaged Instances, VMware to KVM). The NICs are not imported yet at that point, so the device id of the config drive is always kept free.
  • ConfigDriveNetworkElement.CONFIGDRIVEDISKSEQ is public, so it can be used by TemplateManagerImpl.

Notes

  • The volumes which already use the device id 4 on an Instance using config drive (e.g. created before this fix) are not changed: such an Instance still fails to start until the volume is detached.
  • When a NIC of a config drive network is added to a running Instance which was started without config drive, the device id 4 is reserved from then on, but the config drive ISO is only attached the next time the Instance is started.

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?

Unit tests (TemplateManagerImplTest, VolumeApiServiceImplTest, KVMGuruTest, UnmanagedVMsManagerImplTest) cover the device ids of the CD-ROMs with and without config drive (including Instances which have never been started, detected from the network providers, and the config drive location detail), the reserved device ids, the device id allocation for attach volume, restore and import, that the maximum number of data volumes can still be attached, and the error message of an invalid deviceid. They pass on the branch rebased on the latest 4.22.

This branch has not been run on a 4.22 environment. The same logic was tested manually on main (see the results in #14407), with Instances on BIOS and UEFI/q35, with and without config drive, attaching volumes to running and stopped Instances, and importing an unmanaged Instance.

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

  • Instances which have never been started, with config drive networks, with volumes attached while they are stopped
  • Instances which do not use config drive (the device id 4 can still be used by a data volume)
  • the maximum number of data volumes of an Instance using config drive

@weizhouapache

weizhouapache commented Sep 7, 2026 •

Copy link
Copy Markdown
Member Author

Tested with

  • Ubuntu 24.04 cloud image
  • machine type is q35
  • UEFI=SECURE
  • rootdiskcontroller = scsi
  • datadiskcontroller = scsi
image

Note: still got error org.libvirt.LibvirtException: internal error: No more available PCI slots if disk controllers are virtio

image

@weizhouapache
weizhouapache requested a lite review from Copilot September 7, 2026 14:13
@weizhouapache weizhouapache added this to the 4.22.2 milestone Sep 7, 2026
@codecov

codecov Bot commented Sep 7, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 91.46341% with 7 lines in your changes missing coverage. Please review.
✅ Project coverage is 18.32%. Comparing base (c4c9731) to head (7afd3e9).

Files with missing lines Patch % Lines
...er/src/main/java/com/cloud/hypervisor/KVMGuru.java 80.00% 2 Missing ⚠️
...n/java/com/cloud/template/TemplateManagerImpl.java 94.11% 1 Missing and 1 partial ⚠️
.../apache/cloudstack/vm/UnmanagedVMsManagerImpl.java 86.66% 2 Missing ⚠️
...n/java/com/cloud/storage/VolumeApiServiceImpl.java 95.45% 0 Missing and 1 partial ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##               4.22   #14073      +/-   ##
============================================
+ Coverage     18.31%   18.32%   +0.01%     
- Complexity    16633    16663      +30     
============================================
  Files          5939     5939              
  Lines        537748   537802      +54     
  Branches      65924    65933       +9     
============================================
+ Hits          98472    98546      +74     
+ Misses       428070   428047      -23     
- Partials      11206    11209       +3     
Flag Coverage Δ
uitests 4.08% <ø> (ø)
unittests 19.41% <91.46%> (+0.01%) ⬆️

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.

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.

🟡 Changes recommended

Reserving an additional device-id for ConfigDrive without expanding the computed max device-id range can reduce the maximum attachable data volumes and cause avoidable allocation failures.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

This PR addresses KVM/libvirt disk target collisions when ConfigDrive is enabled by ensuring the device-id allocators avoid using the ConfigDrive ISO’s reserved disk sequence (4), preventing duplicate target devices on Q35/UEFI machine types.

Changes:

  • Detect ConfigDrive presence via VmDetailConstants.CONFIG_DRIVE_LOCATION and skip device id CONFIGDRIVEDISKSEQ during device-id allocation.
  • Expose CONFIGDRIVEDISKSEQ publicly so allocators can reference the reserved slot.
  • Update KVM import/restore volume attach path to use the updated allocator logic.
File summaries
File Description
server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java Skip ConfigDrive’s reserved device id during device-id validation/allocation for volume attach.
server/src/main/java/com/cloud/network/element/ConfigDriveNetworkElement.java Make ConfigDrive disk sequence constant publicly accessible.
server/src/main/java/com/cloud/hypervisor/KVMGuru.java Skip ConfigDrive’s reserved device id when selecting the next available device id during VM restore/import flows.
Review details
  • Files reviewed: 3/3 changed files
  • Comments generated: 3
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread server/src/main/java/com/cloud/hypervisor/KVMGuru.java Outdated
Comment thread server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java Outdated
Comment thread server/src/main/java/com/cloud/network/element/ConfigDriveNetworkElement.java Outdated

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

clgtm

Comment thread server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java Outdated
@weizhouapache

Copy link
Copy Markdown
Member Author

need re-work to consider

  • multiple CD-ROMs
  • vm import

moving to draft

cc @DaanHoogland

Comment thread server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java Outdated

@vishesh92 vishesh92 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

clgtm. didn't test.

@weizhouapache weizhouapache changed the title server: Avoid device id collision between config drive ISO and data volumes on KVM server: Avoid device id conflicts between data volumes, the CD-ROM and the config drive ISO Oct 15, 2026
weizhouapache and others added 4 commits October 16, 2026 10:36
…olumes on KVM

ConfigDriveNetworkElement hardcodes disk sequence 4 (CONFIGDRIVEDISKSEQ) for
the config drive ISO, but the volume device-id allocators
(VolumeApiServiceImpl.getDeviceId, KVMGuru.getNextAvailableDeviceId) only
look at persisted VolumeVO rows and have no knowledge that slot 4 is
reserved by the config drive. When a VM using ConfigDrive already has data
disks on device ids 1 and 2, attaching a 3rd data disk gets assigned device
id 4 as well, producing two disks with the same libvirt target device
(e.g. "sde") once both end up on the same bus namespace, as happens with
Q35/UEFI machine types.

Both allocators now skip CONFIGDRIVEDISKSEQ when the VM has a config drive
(detected via the existing CONFIG_DRIVE_LOCATION vm detail), the same way
they already permanently reserve device id 3 for the CD-ROM slot.
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Data volumes could be assigned the same device id as the CD-ROM or the
config drive ISO, which end up with the same libvirt target name (e.g. sde)
when they are on the same bus namespace (SATA with UEFI/Q35).

Add VolumeApiService.getReservedDeviceIds(), which returns the device ids
of the CD-ROM devices and of the config drive ISO when the Instance uses
config drive. The config drive is detected from the network providers
(Dhcp, Dns, UserData), so Instances which have never been started are
covered as well as the ones with the config drive location detail.

The reserved ids are skipped when allocating device ids in:
- attach volume
- restore of volumes and Instances from backup
- import of Instances (unmanaged Instances and VMware to KVM)

The max number of data volumes is preserved when device ids are reserved,
and the error message of an invalid deviceId lists the reserved ids.
Move the calculation of the device ids reserved for the CD-ROM and the
config drive ISO to TemplateManager, as getCdromDeviceIds(). An Instance
has one CD-ROM, and the config drive ISO is one more CD-ROM (device id 4)
when any network of the Instance uses config drive.

VolumeApiService#getReservedDeviceIds() delegates to it, and a variant
with the usage of config drive is added for the cases where the networks
of the Instance are not known yet (VM import and backup restore).
@weizhouapache
weizhouapache requested review from vishesh92 and a lite review from Copilot October 16, 2026 10:47

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.

* @param vm the Instance
* @return the device ids of the CD-ROM devices, including the one of the config drive ISO if the Instance uses config drive
*/
Set<Long> getCdromDeviceIds(VirtualMachine vm);
@weizhouapache

Copy link
Copy Markdown
Member Author

I deployed two Ubuntu 24 VMs on kvm1. t-cd is on the existing L2-configdrive network. t-nocd is on a new l2-noconfigdrive network (VLAN 2500). I hot-attached 5 data volumes to each, then stopped each VM, attached a volume while it was stopped, and started it again.

VM Device ids on hot-attach Device id on stopped attach Domain after restart
t-cd (config drive) 1, 2, 5, 6, 7 8 CD-ROM hdc empty, config drive ISO on hdd, disks vdb, vdc, vdf–vdi, no duplicate target
t-nocd (no config drive) 1, 2, 4, 5, 6 7 CD-ROM hdc empty only, vde (id 4) is a data disk, no clash

With config drive, ids 3 and 4 are reserved for the CD-ROM and the config drive ISO. Without it, only id 3 is reserved, so id 4 is available to a data disk.

@weizhouapache
weizhouapache marked this pull request as ready for review October 16, 2026 11:50

@Damans227 Damans227 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

thanks @weizhouapache, fix looks right. LGTM

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

clgtm

@nvazquez

Copy link
Copy Markdown
Contributor

@blueorangutan package

@blueorangutan

Copy link
Copy Markdown

@nvazquez a [SL] Jenkins job has been kicked to build packages. It will be bundled with KVM, XenServer and VMware 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 19658

@nvazquez

Copy link
Copy Markdown
Contributor

@blueorangutan test

@blueorangutan

Copy link
Copy Markdown

@nvazquez a [SL] Trillian-Jenkins test job (ol8 mgmt + kvm-ol8) has been kicked to run smoke tests

@github-actions

Copy link
Copy Markdown

This pull request has merge conflicts. Dear author, please fix the conflicts and sync your branch with the base branch.

@blueorangutan

Copy link
Copy Markdown

[SF] Trillian test result (tid-17193)
Environment: kvm-ol8 (x2), zone: Advanced Networking with Mgmt server ol8
Total time taken: 56830 seconds
Marvin logs: https://github.com/blueorangutan/acs-prs/releases/download/trillian/pr14073-t17193-kvm-ol8.zip
Smoke tests completed. 148 look OK, 1 have errors, 0 did not run
Only failed and skipped tests results shown below:

Test Result Time (s) Test File
test_01_vpn_usage Error 1.11 test_usage.py

# Conflicts:
#	server/src/main/java/com/cloud/hypervisor/KVMGuru.java
#	server/src/test/java/com/cloud/hypervisor/KVMGuruTest.java
@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 KVM, XenServer and VMware 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 19744

@RosiKyu RosiKyu left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Tested on build 4.22.2.0-shapeblue22281 (head 7afd3e9): 1 management server and 2 KVM hosts, OL 9, qemu-kvm 7.2.0, libvirt 9.0.0, machine type pc-q35-rhel9.2.0, NFS primary storage, NAS backup provider with an NFS repository. The start version was 4.22.1.0, upgraded to the PR build. The baseline was also checked on 4.22.1.1.

LGTM for the reported issue: on q35 config drive VMs the 3rd data volume no longer takes deviceid 4, for running and stopped VMs, and no regression was found.

One related backup case is still open (below); it also fails on 4.22.1.1, so it is not caused by this PR.

Tested/verified

  • Bug reproduced on 4.22.1.0: on a running q35 VM the 3rd data volume fails with target 'sde' duplicated; on a stopped VM it is accepted on deviceid 4 and the VM can no longer start.
  • PR build, q35 scsi config drive VM, running or stopped: the 3rd data volume gets deviceid 5 (sdf), and the VM starts.
  • q35 virtio template: data volumes on 1, 2, 5, and the VM starts.
  • VM without config drive: deviceid 4 is still used and still accepted explicitly (no change).
  • Explicit deviceid=3 and deviceid=4 are rejected on config drive VMs with the new message. deviceid=35 is rejected and deviceid=6 is accepted.
  • The KVM limit of 32 data volumes is still reachable (device ids 1, 2, 5 to 34). The 33rd volume is rejected.
  • After a detach, the lowest free id that is not reserved is reused.
  • Stop/start, reboot and live migration keep the device ids and targets.
  • An ISO attach goes to sdd, and the next data volume skips 3 and 4.
  • A config drive NIC added to a VM with data volumes on 1, 2: the next volume gets 5.
  • Known limitation from the Notes confirmed: a VM that already has a data volume on deviceid 4 and uses config drive still cannot start (target 'sde' duplicated), on a VM upgraded from 4.22.1.0 and on a new VM that gets a config drive NIC. After detach and attach, the volume gets deviceid 5 and the VM starts.
  • Upgrade: the management server on the PR build with agents still on 4.22.1.0 already gives deviceid 5.
  • Upgrade: existing i440fx VMs with a volume on deviceid 4 keep working (stop/start, migration, snapshot). A 32-volume VM from 4.22.1.0 keeps its volumes.
  • Behaviour change: on i440fx VMs with config drive, an explicit deviceid=4 worked on 4.22.1.0 and is now rejected.
  • NAS backup: create a VM from a backup of a config drive VM; restore a backup in place. Both keep device ids 1, 2, 5 and the VM starts.
  • Not covered, below: create a VM from a backup that has a data volume on deviceid 4, on a config drive network.
  • Unmanaged q35 KVM instance with 3 data disks imported into a config drive network: data volumes on 1, 2, 5, and the VM starts.

Not covered in this PR: a VM created from a backup reuses the backup's deviceid 4 on a config drive network

createVMFromBackup takes the device ids of the data volumes from the backup. When the backup has a data volume on deviceid 4 (for example a VM without config drive with 3 data volumes), the new VM on a config drive network cannot start. The same happens on 4.22.1.1, so it is not caused by this PR. It looks related to the open Copilot comment about the device ids assigned when a VM is created. Output below is from the PR build.

  1. Deploy a q35 scsi VM on a network without config drive (running). Attach 3 data volumes. They get device ids 1, 2, 4.
   [root@mgmt1 ~]# cmk deploy virtualmachine name=p14073-i2 displayname=p14073-i2 zoneid=ecdf83eb-0ea4-4668-ba43-ded1680216ba templateid=438f74f5-e450-4ee3-beb4-e03c71a364a0 serviceofferingid=10cf098d-6a06-4474-b18c-a839288cd722 networkids=ac388bab-455d-46bf-a57f-7826489781e0 filter=id,name,state
   {
     "virtualmachine": {
       "id": "b3cb7dbe-6f6b-49e1-8e1b-50101cb7824b",
       "name": "p14073-i2",
       "state": "Running"
     }
   }

   [root@mgmt1 ~]# cmk create volume name=p14073-i2-d1 zoneid=ecdf83eb-0ea4-4668-ba43-ded1680216ba diskofferingid=f71c451a-9be7-4d05-b828-c560c2c5a282 filter=id,name
   {
     "volume": {
       "id": "052bdad4-5a25-4525-bd27-38cdd61896aa",
       "name": "p14073-i2-d1"
     }
   }

   [root@mgmt1 ~]# cmk attach volume id=052bdad4-5a25-4525-bd27-38cdd61896aa virtualmachineid=b3cb7dbe-6f6b-49e1-8e1b-50101cb7824b filter=name,deviceid,state
   {
     "volume": {
       "deviceid": 1,
       "name": "p14073-i2-d1",
       "state": "Ready"
     }
   }

   [root@mgmt1 ~]# cmk create volume name=p14073-i2-d2 zoneid=ecdf83eb-0ea4-4668-ba43-ded1680216ba diskofferingid=f71c451a-9be7-4d05-b828-c560c2c5a282 filter=id,name
   {
     "volume": {
       "id": "0f7d9182-66ac-4cde-9cbf-10d77b0db4e6",
       "name": "p14073-i2-d2"
     }
   }

   [root@mgmt1 ~]# cmk attach volume id=0f7d9182-66ac-4cde-9cbf-10d77b0db4e6 virtualmachineid=b3cb7dbe-6f6b-49e1-8e1b-50101cb7824b filter=name,deviceid,state
   {
     "volume": {
       "deviceid": 2,
       "name": "p14073-i2-d2",
       "state": "Ready"
     }
   }

   [root@mgmt1 ~]# cmk create volume name=p14073-i2-d3 zoneid=ecdf83eb-0ea4-4668-ba43-ded1680216ba diskofferingid=f71c451a-9be7-4d05-b828-c560c2c5a282 filter=id,name
   {
     "volume": {
       "id": "6923452f-7c56-4929-a812-db9f94c365e3",
       "name": "p14073-i2-d3"
     }
   }

   [root@mgmt1 ~]# cmk attach volume id=6923452f-7c56-4929-a812-db9f94c365e3 virtualmachineid=b3cb7dbe-6f6b-49e1-8e1b-50101cb7824b filter=name,deviceid,state
   {
     "volume": {
       "deviceid": 4,
       "name": "p14073-i2-d3",
       "state": "Ready"
     }
   }

   [root@mgmt1 ~]# cmk list volumes virtualmachineid=b3cb7dbe-6f6b-49e1-8e1b-50101cb7824b filter=name,type,deviceid,state -o table
   {
     "count": 4,
     "volume": [
       {
         "deviceid": 0,
         "name": "ROOT-36",
         "state": "Ready",
         "type": "ROOT"
       },
       {
         "deviceid": 1,
         "name": "p14073-i2-d1",
         "state": "Ready",
         "type": "DATADISK"
       },
       {
         "deviceid": 2,
         "name": "p14073-i2-d2",
         "state": "Ready",
         "type": "DATADISK"
       },
       {
         "deviceid": 4,
         "name": "p14073-i2-d3",
         "state": "Ready",
         "type": "DATADISK"
       }
     ]
   }
  1. Assign the VM to the NAS backup offering and take a backup. The backup is BackedUp, and its volume list has "deviceId":4.
   [root@mgmt1 ~]# cmk assign virtualmachinetobackupoffering virtualmachineid=b3cb7dbe-6f6b-49e1-8e1b-50101cb7824b backupofferingid=92135d68-d144-47b1-acd7-a22b44a3c75c
   {
     "success": true
   }

   [root@mgmt1 ~]# cmk create backup virtualmachineid=b3cb7dbe-6f6b-49e1-8e1b-50101cb7824b filter=id,status
   {
     "success": true
   }

   [root@mgmt1 ~]# cmk list backups virtualmachineid=b3cb7dbe-6f6b-49e1-8e1b-50101cb7824b filter=id,name,status,volumes -o json
   {
     "backup": [
       {
         "id": "5d632265-0943-41fc-9521-ed2176b5aa17",
         "name": "p14073-i2-2026-10-27T11:23:07+0000",
         "status": "BackedUp",
         "volumes": "[{\"uuid\":\"a6521e03-a737-48f8-b31f-940e05123cbc\",\"type\":\"ROOT\",\"size\":3758096384,\"path\":\"a6521e03-a737-48f8-b31f-940e05123cbc\",\"deviceId\":0,\"diskOfferingId\":\"8cc9c4e7-6205-4d99-a9b3-cd419116954b\"},{\"uuid\":\"052bdad4-5a25-4525-bd27-38cdd61896aa\",\"type\":\"DATADISK\",\"size\":1073741824,\"path\":\"052bdad4-5a25-4525-bd27-38cdd61896aa\",\"deviceId\":1,\"diskOfferingId\":\"f71c451a-9be7-4d05-b828-c560c2c5a282\"},{\"uuid\":\"0f7d9182-66ac-4cde-9cbf-10d77b0db4e6\",\"type\":\"DATADISK\",\"size\":1073741824,\"path\":\"0f7d9182-66ac-4cde-9cbf-10d77b0db4e6\",\"deviceId\":2,\"diskOfferingId\":\"f71c451a-9be7-4d05-b828-c560c2c5a282\"},{\"uuid\":\"6923452f-7c56-4929-a812-db9f94c365e3\",\"type\":\"DATADISK\",\"size\":1073741824,\"path\":\"6923452f-7c56-4929-a812-db9f94c365e3\",\"deviceId\":4,\"diskOfferingId\":\"f71c451a-9be7-4d05-b828-c560c2c5a282\"}]"
       }
     ],
     "count": 1
   }
  1. Create a VM from the backup on the config drive network. It fails with 530 "Unable to orchestrate the start of VM instance".
   [root@mgmt1 ~]# cmk create vmfrombackup backupid=5d632265-0943-41fc-9521-ed2176b5aa17 zoneid=ecdf83eb-0ea4-4668-ba43-ded1680216ba name=p14073-i2-cd displayname=p14073-i2-cd networkids=b95cd496-0780-459f-ad19-84e6c9f59d59 filter=id,name,state
   {
     "account": "admin",
     "accountid": "2fa6531a-d127-11f1-a593-1e008000020a",
     "cmd": "org.apache.cloudstack.api.command.admin.vm.CreateVMFromBackupCmdByAdmin",
     "completed": "2026-10-27T11:24:53+0000",
     "created": "2026-10-27T11:23:40+0000",
     "domainid": "d6e4d51e-d126-11f1-a593-1e008000020a",
     "domainpath": "ROOT",
     "jobid": "9f557ccc-20c4-4412-bf35-b0b2f319d2f6",
     "jobinstanceid": "eb055867-df6f-4d48-9c24-2ba9db208939",
     "jobinstancetype": "VirtualMachine",
     "jobprocstatus": 0,
     "jobresult": {
       "errorcode": 530,
       "errortext": "Unable to orchestrate the start of VM instance {\"instanceName\":\"i-2-37-VM\",\"uuid\":\"eb055867-df6f-4d48-9c24-2ba9db208939\"}."
     },
     "jobresultcode": 530,
     "jobresulttype": "object",
     "jobstatus": 2,
     "userid": "2fa76435-d127-11f1-a593-1e008000020a"
   }
   🙈 Error: async API failed for job 9f557ccc-20c4-4412-bf35-b0b2f319d2f6
  1. Check the new VM, its volumes and the log. The VM is in Error state, data volume DATA-37-4 is on deviceid 4, and the log has XML error: target 'sde' duplicated for each start attempt.
   [root@mgmt1 ~]# cmk list virtualmachines name=p14073-i2-cd filter=id,name,state,instancename -o json
   {
     "count": 1,
     "virtualmachine": [
       {
         "id": "eb055867-df6f-4d48-9c24-2ba9db208939",
         "instancename": "i-2-37-VM",
         "name": "p14073-i2-cd",
         "state": "Error"
       }
     ]
   }

   [root@mgmt1 ~]# cmk list volumes virtualmachineid=eb055867-df6f-4d48-9c24-2ba9db208939 listall=true filter=id,name,type,deviceid,state -o table
   {
     "count": 4,
     "volume": [
       {
         "deviceid": 0,
         "id": "7dca691a-abeb-48b0-98e7-0bba94ae0470",
         "name": "ROOT-37",
         "state": "Destroy",
         "type": "ROOT"
       },
       {
         "deviceid": 1,
         "id": "c6a92063-3a52-4656-b7b5-718db9368581",
         "name": "DATA-37-1",
         "state": "Destroy",
         "type": "DATADISK"
       },
       {
         "deviceid": 2,
         "id": "506e8aa9-f1ab-49e4-8655-6d8052020396",
         "name": "DATA-37-2",
         "state": "Destroy",
         "type": "DATADISK"
       },
       {
         "deviceid": 4,
         "id": "48a39f80-d01c-4521-91c1-953fc8b76387",
         "name": "DATA-37-4",
         "state": "Destroy",
         "type": "DATADISK"
       }
     ]
   }

   [root@mgmt1 ~]# grep -E 'Unable to start VM on Host' /var/log/cloudstack/management/management-server.log | grep -F '"instanceName":"i-2-37-VM"' | grep -oE '[0-9-]+ [0-9:,]+|Host \{"id":[0-9],"name":"[^"]+"|XML error: [^.]+\.iso'
   2026-10-27 11:24:48,505
   Host {"id":1,"name":"kvm1"
   XML error: target 'sde' duplicated for disk sources '/mnt/6215e536-e762-319c-bf37-fb025da561d1/48a39f80-d01c-4521-91c1-953fc8b76387' and '/mnt/681a96ef-8eb1-3ecc-ac08-be9f5a5b7187/i-2-37-VM.iso
   2026-10-27 11:24:52,955
   Host {"id":1,"name":"kvm1"
   XML error: target 'sde' duplicated for disk sources '/mnt/6215e536-e762-319c-bf37-fb025da561d1/48a39f80-d01c-4521-91c1-953fc8b76387' and '/mnt/681a96ef-8eb1-3ecc-ac08-be9f5a5b7187/i-2-37-VM.iso
  1. Control: create a VM from the same backup on the network without config drive. It is Running with data volumes on 1, 2, 4, so the backup itself is fine.
   [root@mgmt1 ~]# cmk create vmfrombackup backupid=5d632265-0943-41fc-9521-ed2176b5aa17 zoneid=ecdf83eb-0ea4-4668-ba43-ded1680216ba name=p14073-i2-plain displayname=p14073-i2-plain networkids=ac388bab-455d-46bf-a57f-7826489781e0 filter=id,name,state
   {
     "virtualmachine": {
       "id": "10839dd4-ef7b-4fe6-9a56-d2203ec8afe4",
       "name": "p14073-i2-plain",
       "state": "Running"
     }
   }

   [root@mgmt1 ~]# cmk list volumes virtualmachineid=10839dd4-ef7b-4fe6-9a56-d2203ec8afe4 listall=true filter=name,type,deviceid,state -o table
   {
     "count": 4,
     "volume": [
       {
         "deviceid": 0,
         "name": "ROOT-38",
         "state": "Ready",
         "type": "ROOT"
       },
       {
         "deviceid": 1,
         "name": "DATA-38-1",
         "state": "Ready",
         "type": "DATADISK"
       },
       {
         "deviceid": 2,
         "name": "DATA-38-2",
         "state": "Ready",
         "type": "DATADISK"
       },
       {
         "deviceid": 4,
         "name": "DATA-38-4",
         "state": "Ready",
         "type": "DATADISK"
       }
     ]
   }

Workaround

Create the VM from the same backup with explicit device ids that skip 3 and 4 (datadisksdetails). It is Running, with the data volumes on sdb, sdc, sdf, the CD-ROM on sdd and the config drive ISO on sde.

   [root@mgmt1 ~]# cmk create vmfrombackup backupid=5d632265-0943-41fc-9521-ed2176b5aa17 zoneid=ecdf83eb-0ea4-4668-ba43-ded1680216ba name=p14073-i2-cd5 displayname=p14073-i2-cd5 networkids=b95cd496-0780-459f-ad19-84e6c9f59d59 datadisksdetails[0].diskofferingid=f71c451a-9be7-4d05-b828-c560c2c5a282 datadisksdetails[0].deviceid=1 datadisksdetails[1].diskofferingid=f71c451a-9be7-4d05-b828-c560c2c5a282 datadisksdetails[1].deviceid=2 datadisksdetails[2].diskofferingid=f71c451a-9be7-4d05-b828-c560c2c5a282 datadisksdetails[2].deviceid=5 filter=id,name,state
   {
     "virtualmachine": {
       "id": "f26dc8f9-3ebd-48fb-891f-5bc69cd1a5e9",
       "name": "p14073-i2-cd5",
       "state": "Running"
     }
   }

   [root@mgmt1 ~]# cmk list virtualmachines name=p14073-i2-cd5 filter=id,name,state,instancename,hostname -o json
   {
     "count": 1,
     "virtualmachine": [
       {
         "hostname": "kvm2",
         "id": "f26dc8f9-3ebd-48fb-891f-5bc69cd1a5e9",
         "instancename": "i-2-39-VM",
         "name": "p14073-i2-cd5",
         "state": "Running"
       }
     ]
   }

   [root@mgmt1 ~]# cmk list volumes virtualmachineid=f26dc8f9-3ebd-48fb-891f-5bc69cd1a5e9 listall=true filter=name,type,deviceid,state,path -o table
   {
     "count": 4,
     "volume": [
       {
         "deviceid": 0,
         "name": "ROOT-39",
         "path": "005594b8-5b77-4cf2-b47b-f57c316f5771",
         "state": "Ready",
         "type": "ROOT"
       },
       {
         "deviceid": 1,
         "name": "DATA-39-1",
         "path": "ba1831f0-2e05-40c3-8660-9ce4c06d4732",
         "state": "Ready",
         "type": "DATADISK"
       },
       {
         "deviceid": 2,
         "name": "DATA-39-2",
         "path": "4d04b748-3f21-4536-9ee8-bbeb181f026d",
         "state": "Ready",
         "type": "DATADISK"
       },
       {
         "deviceid": 5,
         "name": "DATA-39-5",
         "path": "8dfca59d-d441-4a4b-a86d-299ea2d1862f",
         "state": "Ready",
         "type": "DATADISK"
       }
     ]
   }

   [root@kvm2 ~]# virsh domblklist i-2-39-VM
    Target   Source
   ------------------------------------------------------------------------------------------
    sda      /mnt/6215e536-e762-319c-bf37-fb025da561d1/005594b8-5b77-4cf2-b47b-f57c316f5771
    sdb      /mnt/6215e536-e762-319c-bf37-fb025da561d1/ba1831f0-2e05-40c3-8660-9ce4c06d4732
    sdc      /mnt/6215e536-e762-319c-bf37-fb025da561d1/4d04b748-3f21-4536-9ee8-bbeb181f026d
    sdf      /mnt/6215e536-e762-319c-bf37-fb025da561d1/8dfca59d-d441-4a4b-a86d-299ea2d1862f
    sdd      -
    sde      /mnt/681a96ef-8eb1-3ecc-ac08-be9f5a5b7187/i-2-39-VM.iso

Expected: on a config drive network, the restored data volumes skip deviceid 3 and 4, and the VM starts.
Actual: the device id from the backup is kept, and the VM cannot start.

@DaanHoogland

Copy link
Copy Markdown
Contributor

marked as ready for merge based on tests and reviews. We are n a freeze for 4.22.2 however :/

@RosiKyu

RosiKyu commented Oct 28, 2026

Copy link
Copy Markdown
Collaborator

Follow-up issues for the open cases from testing:

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.

ConfigDrive: duplicated target for disk sources with Q35 machine type

9 participants