Skip to content

Explicitly set model='virtio-scsi' for SCSI controllers on Q35 guests - #193

Open
B-Woody wants to merge 4 commits into
fog:masterfrom
B-Woody:Default-scsi-bus-to-virtio-scsi
Open

Explicitly set model='virtio-scsi' for SCSI controllers on Q35 guests#193
B-Woody wants to merge 4 commits into
fog:masterfrom
B-Woody:Default-scsi-bus-to-virtio-scsi

Conversation

@B-Woody

@B-Woody B-Woody commented Jul 10, 2026

Copy link
Copy Markdown

Problem

When utilising image-based provisioning via Red Hat Satellite (specifically verified on Satellite 6.19.2 running fog-libvirt 0.14.0) onto a libvirt provider, cloud-init user-data fails to execute.

The breakdown occurs because Satellite/fog-libvirt targets a SCSI bus (bus='scsi') to attach the user-data ISO payload on modern Q35 machine types. However, because no explicit controller model is provided in the generated XML, libvirt defaults to a legacy controller emulation type (it was lsilogic on my system).

Modern Red Hat Enterprise Linux (RHEL) minimal/cloud images don't load legacy storage drivers for lsilogic. As a result, the guest kernel cannot see the underlying storage controller, /dev/sda is never initialized inside the VM, and cloud-init fails to detect its datasource.

Solution

This PR injects a conditional check inside the XML builder block within server.rb. If any attached volumes are configured to use a scsi bus, it programmatically forces libvirt to instantiate a modern virtio-scsi controller layout:

if volumes.any? { |v| v.bus == 'scsi' }
  xml.controller(:type => 'scsi', :index => '0', :model => 'virtio-scsi')end

This ensures out-of-the-box compatibility for RHEL cloud images.

Development & Testing Notes

  • Disclaimer: I am not natively a Ruby developer! After troubleshooting and isolating the root cause in the hypervisor XML configurations, I consulted a Large Language Model (LLM) to assist me in mapping the logic safely into the native Nokogiri syntax used by the gem's codebase.

  • Validation: This fix was live-patched directly into server.rb on a production Red Hat Satellite 6.19.2 server running fog-libvirt-0.14.0. Post-patch testing verified that newly provisioned VMs successfully attached the virtual media controller using virtio-scsi. The guest kernels immediately mapped the volume to /dev/sda, allowing cloud-init to fetch the metadata source and run the commands in user-data.

Comment thread lib/fog/libvirt/models/compute/server.rb Outdated
xml.address(:type => "drive", :controller => 0, :bus => 0, :unit => 0)
end
end
if volumes.any? { |v| v.bus == 'scsi' }

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.

Tests fail with this:

Error saving the server: undefined method `bus' for     <Fog::Libvirt::Compute::Volume

Not sure if this is due to the mock driver we're using, but in the docs I can't find a reference. I can see sometimes we're setting it as part of the target though.

@B-Woody

B-Woody commented Jul 10, 2026

Copy link
Copy Markdown
Author

Apologies for the test failure!

According to the LLM:

I encountered a structural edge case where raw storage volumes are passed to the server model during unit testing, which do not expose a .bus method natively.

I have updated the conditional statement to defensively verify object methods using respond_to?(:bus) alongside checking nested disk definitions. This prevents the NoMethodError and allows the test suite to pass cleanly while retaining the core fix for the provisioning workflow.

When I tested it on a live server I just had a straight device definition without the if condition:

xml.controller(:type => 'scsi', :index => '0', :model => 'virtio-scsi')

I'm a bit out of my depth here, as I'm not a Ruby dev. I'll step out of the way and let some more experienced folks take a look. Hopefully it's almost there.

@B-Woody

B-Woody commented Jul 28, 2026

Copy link
Copy Markdown
Author

Hi,

Just wondering if this needs any changes to be merged?

Initially this was just to fix an edge case in my homelab, but as it turns out, I now have a customer who may run into a similar issues eventually, as they're looking to do image-based provisioning from Satellite with some RHEL KVM/libvirt hosts.

If this needs changes I'd be happy to take another look at it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants