gw769 commented on issue #12090:
URL: https://github.com/apache/cloudstack/issues/12090#issuecomment-3580204996
Hi all,
I've found a **temporary workaround** for this issue (see #12090) using
CloudStack's libvirt VM XML transformation hook. Here's the properly formatted
details:
## Workaround Approach
Use the `libvirt-vm-xml-transformer.groovy` hook to force-inject 4
persistent `virtio-scsi` controllers (index=1~4) into the VM's XML. This
prevents the unwanted `lsilogic` controller from being added after reboot.
## Steps to Apply
1. **Create/Update the Hook File**
Create/overwrite the hook at:
```bash
/etc/cloudstack/agent/hooks/libvirt-vm-xml-transformer.groovy
```
2. **Add the Workaround Script**
Paste this code (properly wrapped in a Groovy code block):
```groovy
import org.apache.logging.log4j.Logger
class VmWwnHook {
/**
* Transform XML by injecting required virtio-scsi controllers
* @param log Logger instance for logging
* @param xml Original XML string to process
* @return Modified XML (or original on exception)
*/
public String transform(Logger log, String xml) {
try {
log.info("[VM-WWN-HOOK] Starting: Inject virtio-scsi
controllers")
log.debug("[VM-WWN-HOOK] Original XML:\n${xml}")
String modifiedXml = xml
modifiedXml = injectVirtioScsiControllers(log, modifiedXml)
log.debug("[VM-WWN-HOOK] Modified XML:\n${modifiedXml}")
return modifiedXml
} catch (Exception e) {
log.error("[VM-WWN-HOOK] Execution error: ${e.getMessage()}",
e)
return xml
}
}
/**
* Force inject 4 virtio-scsi controllers (index=1~4), skip if exists
* @param log Logger instance
* @param xml Original XML string
* @return XML with virtio-scsi controllers injected
*/
private String injectVirtioScsiControllers(Logger log, String xml) {
try {
log.info("[VM-WWN-HOOK] Injecting virtio-scsi controllers
(index=1~4)")
String modifiedXml = xml
String controllersToInject = ""
// Check & inject controllers 1-4
for (int i = 1; i <= 4; i++) {
String checkStr = "controller type='scsi' index='${i}'"
if (!modifiedXml.contains(checkStr)) {
controllersToInject += """
<controller type='scsi' index='${i}' model='virtio-scsi'>
<driver queues='4'/>
</controller>"""
log.info("[VM-WWN-HOOK] Injecting missing controller
(index=${i})")
} else {
log.info("[VM-WWN-HOOK] Controller (index=${i})
exists - skipping")
}
}
// Inject into XML
if (!controllersToInject.isEmpty()) {
def existingScsiMatcher = modifiedXml =~
/(?s)(<controller type='scsi'.*?<\/controller>)/
if (existingScsiMatcher.find()) {
String lastController =
existingScsiMatcher[existingScsiMatcher.count - 1][1]
modifiedXml = modifiedXml.replace(lastController,
lastController + "\n" + controllersToInject)
log.info("[VM-WWN-HOOK] Injected after existing
controllers")
} else {
modifiedXml = modifiedXml.replace("<devices>",
"<devices>\n" + controllersToInject)
log.info("[VM-WWN-HOOK] Injected into <devices> tag")
}
} else {
log.info("[VM-WWN-HOOK] All controllers exist - no
injection needed")
}
return modifiedXml
} catch (Exception e) {
log.error("[VM-WWN-HOOK] Injection error: ${e.getMessage()}",
e)
return xml
}
}
}
def vmWwnHook = new VmWwnHook()
```
## Verification
After applying:
- Reboot the VM, then run `virsh dumpxml <VM_NAME> | grep controller `
- All SCSI controllers will show `model='virtio-scsi'` (no more `lsilogic`),
and all disks remain recognized.
```
root@NODE159:/etc/cloudstack/agent/hooks# virsh dumpxml i-2-971-VM | grep
controll
<address type='drive' controller='0' bus='0' target='0' unit='0'/>
<address type='drive' controller='0' bus='0' target='0' unit='1'/>
<address type='drive' controller='0' bus='0' target='0' unit='2'/>
<address type='drive' controller='0' bus='0' target='0' unit='4'/>
<address type='drive' controller='0' bus='0' target='0' unit='5'/>
<address type='drive' controller='0' bus='0' target='0' unit='6'/>
<address type='drive' controller='1' bus='0' target='0' unit='0'/>
<controller type='usb' index='0' model='qemu-xhci'>
</controller>
<controller type='scsi' index='0' model='virtio-scsi'>
</controller>
<controller type='scsi' index='1' model='virtio-scsi'>
</controller>
<controller type='scsi' index='2' model='virtio-scsi'>
</controller>
<controller type='scsi' index='3' model='virtio-scsi'>
</controller>
<controller type='scsi' index='4' model='virtio-scsi'>
</controller>
<controller type='pci' index='0' model='pcie-root'>
</controller>
<controller type='virtio-serial' index='0'>
</controller>
<controller type='pci' index='1' model='pcie-root-port'>
</controller>
<controller type='pci' index='2' model='pcie-root-port'>
</controller>
<controller type='pci' index='3' model='pcie-root-port'>
</controller>
<controller type='pci' index='4' model='pcie-root-port'>
</controller>
<controller type='pci' index='5' model='pcie-root-port'>
</controller>
<controller type='pci' index='6' model='pcie-root-port'>
</controller>
<controller type='pci' index='7' model='pcie-root-port'>
</controller>
<controller type='pci' index='8' model='pcie-root-port'>
</controller>
<controller type='pci' index='9' model='pcie-root-port'>
</controller>
<controller type='pci' index='10' model='pcie-to-pci-bridge'>
</controller>
<controller type='pci' index='11' model='pcie-root-port'>
</controller>
<controller type='pci' index='12' model='pcie-root-port'>
</controller>
<address type='virtio-serial' controller='0' bus='0' port='1'/>
```
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]