Repository navigation
server: Avoid device id conflicts between data volumes, the CD-ROM and the config drive ISO - #14073
weizhouapache wants to merge 5 commits into
Conversation
Codecov Report❌ Patch coverage is 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
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:
|
There was a problem hiding this comment.
🟡 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_LOCATIONand skip device idCONFIGDRIVEDISKSEQduring device-id allocation. - Expose
CONFIGDRIVEDISKSEQpublicly 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.
|
need re-work to consider
moving to draft |
…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).
4eab500 to
a28af1a
Compare
| * @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); |
|
I deployed two Ubuntu 24 VMs on kvm1.
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. |
Damans227
left a comment
There was a problem hiding this comment.
thanks @weizhouapache, fix looks right. LGTM
|
@blueorangutan package |
|
@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. |
|
Packaging result [SF]: ✔️ el8 ✔️ el9 ✔️ el10 ✔️ debian ✔️ suse15. SL-JID 19658 |
|
@blueorangutan test |
|
@nvazquez a [SL] Trillian-Jenkins test job (ol8 mgmt + kvm-ol8) has been kicked to run smoke tests |
|
This pull request has merge conflicts. Dear author, please fix the conflicts and sync your branch with the base branch. |
|
[SF] Trillian test result (tid-17193)
|
# Conflicts: # server/src/main/java/com/cloud/hypervisor/KVMGuru.java # server/src/test/java/com/cloud/hypervisor/KVMGuruTest.java
|
@blueorangutan package |
|
@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. |
|
Packaging result [SF]: ✔️ el8 ✔️ el9 ✔️ el10 ✖️ debian ✔️ suse15. SL-JID 19744 |
RosiKyu
left a comment
There was a problem hiding this comment.
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=3anddeviceid=4are rejected on config drive VMs with the new message.deviceid=35is rejected anddeviceid=6is 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=4worked 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.
- 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"
}
]
}
- 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
}
- 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
- 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' duplicatedfor 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
- 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.
|
marked as ready for merge based on tests and reviews. We are n a freeze for 4.22.2 however :/ |
|
Follow-up issues for the open cases from testing:
|





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 withtarget '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
0341,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):
31,2,4,5,6,73,41,2,5,6,7,8An 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 fromCDROM_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 inTemplateManagerImpl.VolumeApiService.getReservedDeviceIds(vm)(and the variant withconfigDriveUsed) returns these device ids. It is used when allocating device ids in:deviceidparameter, whose error message now lists the reserved ids). This also covers Instances which are stopped.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.ConfigDriveNetworkElement.CONFIGDRIVEDISKSEQis public, so it can be used byTemplateManagerImpl.Notes
Types of changes
Feature/Enhancement Scale or Bug Severity
Feature/Enhancement Scale
Bug Severity
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 invaliddeviceid. 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?