Bug 1581414

Summary: [RFE][OSP 17] Record instance machine types at service startup and instance spawn allowing [libvirt]hw_machine_type to be changed for q35
Product: Red Hat OpenStack Reporter: Eduardo Habkost <ehabkost>
Component: openstack-novaAssignee: Lee Yarwood <lyarwood>
Status: CLOSED ERRATA QA Contact: James Parker <jparker>
Severity: high Docs Contact:
Priority: medium    
Version: 14.0 (Rocky)CC: ailan, alifshit, bdobreli, dasmith, egallen, eglynn, fjin, igallagh, jhakimra, jparker, kchamart, kfida, lyarwood, mariel, nlevinki, rjones, sbauza, sgordon, spower, srevivo, stephenfin, vromanso
Target Milestone: betaKeywords: FutureFeature, Patch, Reopened, Triaged
Target Release: 17.1   
Hardware: x86_64   
OS: Linux   
Whiteboard:
Fixed In Version: openstack-nova-23.0.3-0.20210908140341.e39bbdc.el9ost Doc Type: Enhancement
Doc Text:
Before this release, `NovaHWMachineType` could not be changed for the lifetime of a RHOSP deployment because the machine type of instances without a `hw_machine_type` image property would use the newly configured machine types after a hard reboot or migration. Changing the underlying machine type for an instance could break the internal ABI of the instance. + With this release, when launching an instance the Compute service records the instance machine type within the system metadata of the instance. Therefore, it is now possible to change the `NovaHWMachineType` during the lifetime of a RHOSP deployment without affecting the machine type of existing instances.
Story Points: ---
Clone Of:
: 1821559 1905198 1944607 (view as bug list) Environment:
Last Closed: 2023-08-16 01:09:22 UTC Type: Bug
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version: Wallaby
Embargoed:
Bug Depends On: 1602889, 1614127, 1716356, 1946898    
Bug Blocks: 1517362, 1821559, 1905198, 1944607    

Description Eduardo Habkost 2018-05-22 17:28:47 UTC
We plan to change the default machine-type to "q35" in qemu-kvm-rhev, but we want to ensure no management system will break when we do that.  To do this, we need to ensure there's no code in OpenStack that assumes an omitted machine-type means libvirt+QEMU will always default to "pc".

If you believe OpenStack won't break when we change the default machine-type to "q35", please mark this bug as TestOnly.

Comment 1 Kashyap Chamarthy 2018-05-22 21:42:28 UTC
(In reply to Eduardo Habkost from comment #0)
> We plan to change the default machine-type to "q35" in qemu-kvm-rhev, but we
> want to ensure no management system will break when we do that.  To do this,
> we need to ensure there's no code in OpenStack that assumes an omitted
> machine-type means libvirt+QEMU will always default to "pc".
> 
> If you believe OpenStack won't break when we change the default machine-type
> to "q35", please mark this bug as TestOnly.

I think OpenStack Nova still needs work in this area.

Currently, the support for Q35 is "bare bones"; as in: if you explicitly configure a Nova Compute node to use Q35 machine type, then all instances launched from that point on that Compute node will use it.

But I learnt (from libvirt developer Andrea Bolognani) that something like the above will will probably quickly break down as soon as you try to hot-plug devices, etc. And that Q35 is just different enough from 'i440fx' that Nova has to account for both types at some point.

Comment 2 Eduardo Habkost 2018-05-23 17:01:18 UTC
Note that if Nova still doesn't work well with q35, you are free to choose "pc" as the default on Nova.  The scope of this BZ is to make Nova not assume that "pc" is the default on libvirt+QEMU (which would be a bug on Nova).

You don't need to make Nova work well with q35 out of the box (which would be a feature, not a bug fix), or make q35 the default on Nova (which would also be a new feature).

Comment 3 Matthew Booth 2018-05-24 15:03:30 UTC
Nova has no default machine type for libvirt. We allow it to be configured explicitly, but if it is not specified we have no hard-coded default.

Comment 6 Kashyap Chamarthy 2018-05-25 11:56:13 UTC
(In reply to Matthew Booth from comment #3)
> Nova has no default machine type for libvirt. We allow it to be configured
> explicitly, but if it is not specified we have no hard-coded default.
tl;dr: From the past few hours of research, it _looks_ like Nova doesn't
any work to handle QEMU changing machine type default to 'q35' from
'pc'.  However, I was told that to make 'q35' work *correctly* in
context of PCIe, there may need to some more work.

Long
----

While what you say is correct (Nova today allows configuring machine
type either via per-image metadata property or via setting per-Compute
node config), but what Eduardo is:

    If / when QEMU switches default machine type to 'Q35', is something
    likely to break in Nova?

Let's try to answer that below.

Nova by default does *not* hard-code any machine type; it just uses
whatever libvirt gives it on default.  All it does is allow configuring
machine type in two ways: 

  (1) Disk image metadata property, so that when you boot a guest from
      that disk image, it gets the configured machine type.

  (2) Per-Compute host configuration file, so that _all_ guests launched
      on that host gets the configured machine type.

    * * *

From a discussion with Andrea Bolognani from libvirt on IRC, management
applications (like Nova) are likely to break _only_ if we have a code
pattern like:

   if (q35_explicitly_requested) {do_q35_thing();} else {do_pc_thing();}

But -- Nova doesn't have any such.  

Auditing the Nova code[+], the only place where we explicitly take 'q35'
into consideration is during PCIe ports (from
nova/virt/libvirt/driver.py), from _get_guest_config() function:

        [...]   
        # Add PCIe root port controllers for PCI Express machines
        # but only if their amount is configured
        if (CONF.libvirt.num_pcie_ports and
                ((caps.host.cpu.arch == fields.Architecture.AARCH64 and
                guest.os_mach_type.startswith('virt')) or
                (caps.host.cpu.arch == fields.Architecture.X86_64 and
                guest.os_mach_type is not None and
                'q35' in guest.os_mach_type))):
            self._guest_add_pcie_root_ports(guest)
        [...]   

The above code is fine because it is looking directly at the guest
configuration, so it will work correctly regardless of whether the guest
is 'q35', because the user explicitly asked for it or because it's the
default machine type.

Further, Nova's (also from libvirt/driver.py) _get_machine_type() is
called only from one other function, _configure_guest_by_virt_type(),
during guest definition time:

    [...]
    guest.os_mach_type = self._get_machine_type(image_meta, caps)
    [...]

Here too, _get_machine_type() is called *only* at guest definition time.
So long as we are calling  _get_machine_type() *only* at guest
definition time, we seemt to be good with respect to handling QEMU
changing default from 'pc' to 'q35'.

Correct me if I am wrong.

[*] http://git.openstack.org/cgit/openstack/nova/commit/?id=a234bbf8 --
    Allow to configure amount of PCIe ports

Comment 7 Eduardo Habkost 2018-05-25 20:21:27 UTC
The amount of detail in this discussion is huge, so I will try to limit the scope of this BZ, first:

1) The original BZ mentioned deprecating "pc", but that's not being considered anymore.

2) The default in qemu-kvm-rhev is going to be changed from "pc" to "q35".  If this is going to break something for OpenStack users (anything), this needs to be addressed in OpenStack somehow.

That's all.  This doesn't mean OpenStack needs to work with q35 out of the box, but this means OpenStack might need to explicitly ask for "pc" if you know "q35" will break something for users.

Things get more complex where "break something for users" might be caused by subtle incompatibilities elsewhere: e.g. users importing existing guest images that work only with "pc", and now they won't work out of the box anymore.

It's up for you to decide how to handle this.  Maybe the easiest solution is to keep "pc" as default until we have better mechanisms for automatically choosing a smarter default after looking at a disk image.


I'll try to be answer more specific points below:

(In reply to Kashyap Chamarthy from comment #6)
> (In reply to Matthew Booth from comment #3)
> > Nova has no default machine type for libvirt. We allow it to be configured
> > explicitly, but if it is not specified we have no hard-coded default.
> tl;dr: From the past few hours of research, it _looks_ like Nova doesn't
> any work to handle QEMU changing machine type default to 'q35' from
> 'pc'.  However, I was told that to make 'q35' work *correctly* in
> context of PCIe, there may need to some more work.

This seems to mean "yes, something is going to break if the default is changed to q35".  Doesn't it?

> 
> Long
> ----
> 
> While what you say is correct (Nova today allows configuring machine
> type either via per-image metadata property or via setting per-Compute
> node config), but what Eduardo is:
> 
>     If / when QEMU switches default machine type to 'Q35', is something
>     likely to break in Nova?

Note that "something breaking in Nova" is much more specific than "something breaking for an OpenStack user".  Even if Nova is 100% bug free, users might still have problems caused by the change to q35.


> 
> Let's try to answer that below.
> 
> Nova by default does *not* hard-code any machine type; it just uses
> whatever libvirt gives it on default.  All it does is allow configuring
> machine type in two ways: 
> 
>   (1) Disk image metadata property, so that when you boot a guest from
>       that disk image, it gets the configured machine type.
> 
>   (2) Per-Compute host configuration file, so that _all_ guests launched
>       on that host gets the configured machine type.
> 
>     * * *
> 
> From a discussion with Andrea Bolognani from libvirt on IRC, management
> applications (like Nova) are likely to break _only_ if we have a code
> pattern like:
> 
>    if (q35_explicitly_requested) {do_q35_thing();} else {do_pc_thing();}
> 
> But -- Nova doesn't have any such.  

What about existing guest images that will break if booted using q35?  What about having pc-specific code that isn't even marked as pc-specific but breaks if the machine type is q35?  Finding these cases might be difficult.


> 
[...]
> Here too, _get_machine_type() is called *only* at guest definition time.
> So long as we are calling  _get_machine_type() *only* at guest
> definition time, we seemt to be good with respect to handling QEMU
> changing default from 'pc' to 'q35'.

I don't think we can be sure about that without extensive testing.  Are you sure there isn't pc-specific code not documented as pc-specific anywhere else?

But, anyway, even if OpenStack is considered ready to use q35 by default, probably the main issue (and most complex one) is breaking things for users having pc-specific disk images that worked out of the box.

Comment 8 Kashyap Chamarthy 2018-05-28 11:10:34 UTC
[Meta comment: Given Eduardo's comment above, removing 'Triaged' and 'TestOnly' keywords, and moving the bug back to 'NEW', to not let it drop off our radar.  Matt, feel free to override this, if you think no work needs doing given comment#7.]

Comment 9 Eduardo Habkost 2018-05-29 14:36:31 UTC
Changing bug summary to make the intent clearer.

I believe the best option for OpenStack is to have its own default, and keep it as "pc" initially.

Changing OpenStack's default "q35" would be a larger task that OpenStack developers should  probably plan for, but this is not in the scope of this BZ.

Comment 11 Daniel Berrangé 2018-06-01 14:23:33 UTC
To further clarify what Eduardo says, the specific code pattern we want to avoid is something like

   if guest machine type == q35:
       ... do something q35 related...
   else
       ... do something pc related...

As this code pattern is assuming that not setting a machine type results in pc.

I can see exactly this bug pattern in current Nova code:

        # Add PCIe root port controllers for PCI Express machines
        # but only if their amount is configured
        if (CONF.libvirt.num_pcie_ports and
                ((caps.host.cpu.arch == fields.Architecture.AARCH64 and
                guest.os_mach_type.startswith('virt')) or
                (caps.host.cpu.arch == fields.Architecture.X86_64 and
                guest.os_mach_type is not None and
                'q35' in guest.os_mach_type))):
            self._guest_add_pcie_root_ports(guest)


This is assuming that when  guest.os_mach_type == None, then you have 'pc' machine type, which is not going to be valid in future.

Currently guest.os_mach_type is only set if the image / flavour metadata requests a non-default machine type, or if nova.conf does so.

To fix this Nova needs to make sure guest.os_mach_type is always set.

The "easy" way todo this is to just hardcode it to "pc" on x86, or other platform specific machine type.

The better way todo this is to query the libvirt capabilities XML to extract the default machine type.

Comment 12 Kashyap Chamarthy 2018-06-01 15:07:55 UTC
(In reply to Daniel Berrange from comment #11)
> To further clarify what Eduardo says, the specific code pattern we want to
> avoid is something like
> 
>    if guest machine type == q35:
>        ... do something q35 related...
>    else
>        ... do something pc related...
> 
> As this code pattern is assuming that not setting a machine type results in
> pc.
> 
> I can see exactly this bug pattern in current Nova code:
> 
>         # Add PCIe root port controllers for PCI Express machines
>         # but only if their amount is configured
>         if (CONF.libvirt.num_pcie_ports and
>                 ((caps.host.cpu.arch == fields.Architecture.AARCH64 and
>                 guest.os_mach_type.startswith('virt')) or
>                 (caps.host.cpu.arch == fields.Architecture.X86_64 and
>                 guest.os_mach_type is not None and
>                 'q35' in guest.os_mach_type))):
>             self._guest_add_pcie_root_ports(guest)
> 
> 
> This is assuming that when  guest.os_mach_type == None, then you have 'pc'
> machine type, which is not going to be valid in future.
> 
> Currently guest.os_mach_type is only set if the image / flavour metadata
> requests a non-default machine type, or if nova.conf does so.
> 
> To fix this Nova needs to make sure guest.os_mach_type is always set.
> 
> The "easy" way todo this is to just hardcode it to "pc" on x86, or other
> platform specific machine type.
> 
> The better way todo this is to query the libvirt capabilities XML to extract
> the default machine type.

Thanks for the analysis Dan.  (I should point out that I was wrong in comment#6 on my analysis that the above code snippet is okay; it's not -- for the reasons Dan outlined.)

As discussed on IRC, Nova should aim to go with the better approach: and since Nova already supplies host capabilities into _get_machine_type(), so that we won't return 'None'.

Comment 14 Eduardo Habkost 2018-07-18 18:18:28 UTC
I have opened bug 1602889 against libosinfo, and I'm adding it as a dependency of this bug.

If you plan to address this bug without libosinfo help first, I recommend opening a separate BZ against this component to ensure the component will eventually use libosinfo to choose the machine-type.  Please let me know if a separate BZ will be needed.

Comment 15 Eduardo Habkost 2018-08-03 20:33:35 UTC
Important update: I have just noticed that even when using q35, the default NIC and sound card model in libvirt are legacy PCI devices that end up requiring a legacy PCI bridge to be added to the VM: rtl8139 and ich6-hda-intel.

New action items for libosinfo and all libvirt users:
* libosinfo also needs to provide a recommendation of sound hardware
* In addition to prefer Q35 when possible, management software should prefer the 'ich9-hda-intel' sound card and 'e1000e' NIC when using Q35.


In other words, the recommendations are:

- If there's no user input about machine-type:
-- If guest OS is known, use libosinfo
-- If guest OS is unknown, prefer Q35

- If using Q35:
-- If there's no user input about NIC model:
--- If guest OS is known, use libosinfo
--- If guest OS is unknown, prefer e1000e
-- If there's no user input about sound card model:
--- If guest OS is known, use libosinfo
--- If guest OS is unknown or libosinfo has no sound card recommendation, prefer ich9

Comment 16 Eduardo Habkost 2018-08-09 03:15:30 UTC
We have one additional issue with RHEL-6 guests: they don't have drivers for virtio-1, so they need virtio devices to run in legacy mode.  So I'm extending the scope of this BZ (and related ones) again.

Full list of action items, for reference:
On libosinfo:
* libosinfo should provide a recommendation of machine-type
* libosinfo should provide a recommendation of sound hardware
* libosinfo should tell if the guest OS supports only legacy virtio and/or modern virtio

On management software:
* Management software should use libosinfo to pick default machine-type, and prefer Q35 when possible
* Management software should prefer the 'ich9-hda-intel' sound card and 'e1000e' NIC when using Q35.
* Management software should do what's necessary if guest supports only legacy virtio. Options to ensure that:
** Use "pc" machine type
** Use a libvirt flag that will force the virtio device to be in legacy mode (not available yet, I will open a BZ for this)
** Manually plug the virtio device to a legacy PCI bus (probably not feasible as it would require duplicating the libvirt PCI address allocation logic)

I'm not opening separate BZs for each item above because it's up to the maintainer of each component to decide how to track these tasks.

Comment 19 Kashyap Chamarthy 2018-08-28 17:14:45 UTC
(In reply to Eduardo Habkost from comment #16)
> We have one additional issue with RHEL-6 guests: they don't have drivers for
> virtio-1, so they need virtio devices to run in legacy mode.  So I'm
> extending the scope of this BZ (and related ones) again.
> 
> Full list of action items, for reference:
> On libosinfo:
> * libosinfo should provide a recommendation of machine-type
> * libosinfo should provide a recommendation of sound hardware
> * libosinfo should tell if the guest OS supports only legacy virtio and/or
> modern virtio
> 
> On management software:
> * Management software should use libosinfo to pick default machine-type, and
> prefer Q35 when possible
> * Management software should prefer the 'ich9-hda-intel' sound card and
> 'e1000e' NIC when using Q35.
> * Management software should do what's necessary if guest supports only
> legacy virtio. Options to ensure that:
> ** Use "pc" machine type
> ** Use a libvirt flag that will force the virtio device to be in legacy mode
> (not available yet, I will open a BZ for this)
> ** Manually plug the virtio device to a legacy PCI bus (probably not
> feasible as it would require duplicating the libvirt PCI address allocation
> logic)
> 
> I'm not opening separate BZs for each item above because it's up to the
> maintainer of each component to decide how to track these tasks.

Meta comment: From what I understand, and from my discussion with Dan Berrangé (refer: https://bugzilla.redhat.com/show_bug.cgi?id=1585798#c2), this item involving libosinfo in comment#16 and your comment#15 should be done as separate work items as part of: https://bugzilla.redhat.com/show_bug.cgi?id=1585798

Comment 22 Matthew Booth 2019-10-15 09:45:41 UTC
I am closing this bug as it has not been addressed for a very long time. Please feel free to reopen if it is still relevant.

Comment 25 Kashyap Chamarthy 2019-10-16 07:36:55 UTC
Closing this as WONTFIX is incorrect; re-opening it.  As 'pc' / 'i440fx' machine type is slated for deprecation, and Nova needs to be ready to handle it.

I don't think this is being tracked anywhere else in Red Hat bugzilla.

There is an upstream bug: 

    https://bugs.launchpad.net/nova/+bug/1780138
    Don't assume the guest machine type to be of 'pc' 

And a WIP Nova specification (started in Jan 2019):

    https://review.opendev.org/#/c/631154/
    WIP: Gracefully handle QEMU machine types for guests

Comment 30 spower 2022-06-03 13:36:38 UTC
This RFE was not marked as MVP for OSP 17.0 and so will be re targeted for consideration for verification and docs in OSP 17.1. If Tech Preview for OSP 17.0 is required please clone bug and contact rhos-trac with details.

Comment 49 errata-xmlrpc 2023-08-16 01:09:22 UTC
Since the problem described in this bug report should be
resolved in a recent advisory, it has been closed with a
resolution of ERRATA.

For information on the advisory (Release of components for Red Hat OpenStack Platform 17.1 (Wallaby)), and where to find the updated
files, follow the link below.

If the solution does not work for you, open a new bug report.

https://access.redhat.com/errata/RHEA-2023:4577