libvirt get_host_capabilities() duplicates features

Bug #1322702 reported by Loganathan Parthipan
12
This bug affects 2 people
Affects Status Importance Assigned to Milestone
OpenStack Compute (nova)
Fix Released
Undecided
Loganathan Parthipan

Bug Description

get_host_capabilities() in libvirt driver seems to have a bug that will result in duplicated features.

def get_host_capabilities(self):
        """Returns an instance of config.LibvirtConfigCaps representing
           the capabilities of the host.
        """
        if not self._caps:
            xmlstr = self._conn.getCapabilities()
            self._caps = vconfig.LibvirtConfigCaps()
            self._caps.parse_str(xmlstr)
            if hasattr(libvirt, 'VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES'):
                try:
                    features = self._conn.baselineCPU(
                        [self._caps.host.cpu.to_xml()],
                        libvirt.VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES)
                    # FIXME(wangpan): the return value of baselineCPU should be
                    # None or xml string, but libvirt has a bug
                    # of it from 1.1.2 which is fixed in 1.2.0,
                    # this -1 checking should be removed later.
                    if features and features != -1:
                        self._caps.host.cpu.parse_str(features)
                except libvirt.libvirtError as ex:
                    error_code = ex.get_error_code()
                    if error_code == libvirt.VIR_ERR_NO_SUPPORT:
                        LOG.warn(_LW("URI %(uri)s does not support full set"
                                     " of host capabilities: " "%(error)s"),
                                     {'uri': self.uri(), 'error': ex})
                    else:
                        raise
        return self._caps

The _caps.parse_str() is called in sequence for both capabilites and expand features. Since capabilities will have certain features in a VM, and these will be repeated again in the expand features, the _caps.host.cpu.features will end up with duplicated features. This will cause cpu compare to fail later.

(nova)root@overcloud-novacompute0-un6ckrnp5tzl:~# python
Python 2.7.6 (default, Mar 22 2014, 22:59:38)
[GCC 4.8.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import libvirt
>>> conn = libvirt.open("qemu:///system")
>>> from nova.virt.libvirt import config as vconfig
>>> caps = vconfig.LibvirtConfigCaps()
>>> xmlstr = conn.getCapabilities()
>>> caps.parse_str(xmlstr)
>>> features = conn.baselineCPU([caps.host.cpu.to_xml()], libvirt.VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES)
>>> caps.host.cpu.parse_str(features)
>>> for f in caps.host.cpu.features:
... print f.name
...
hypervisor
popcnt
hypervisor
popcnt
pni
sse2
sse
fxsr
mmx
pat
cmov
pge
sep
apic
cx8
mce
pae
msr
tsc
pse
de
fpu
>>>

summary: - libvirt get_host_capabilities duplicates
+ libvirt get_host_capabilities duplicates features
summary: - libvirt get_host_capabilities duplicates features
+ libvirt get_host_capabilities() duplicates features
Revision history for this message
Marwan AKIKI (marwan-akiki) wrote :

I have bypassed it by adding 2 lines of code to driver.py

    def get_host_capabilities(self):
        """Returns an instance of config.LibvirtConfigCaps representing
           the capabilities of the host.
        """
        if not self._caps:
            xmlstr = self._conn.getCapabilities()
            self._caps = vconfig.LibvirtConfigCaps()
            self._caps.parse_str(xmlstr)
            if hasattr(libvirt, 'VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES'):
                try:
                    features = self._conn.baselineCPU(
                        [self._caps.host.cpu.to_xml()],
                        libvirt.VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES)

                    # Add Code to remove duplicate Features (Marwan AKIKI)
                    for f in self._caps.host.cpu.features:
                        features=features.replace(" <feature policy='require' name='" + f.name + "'/>\n", '')

                    # FIXME(wangpan): the return value of baselineCPU should be
                    # None or xml string, but libvirt has a bug
                    # of it from 1.1.2 which is fixed in 1.2.0,
                    # this -1 checking should be removed later.
                    if features and features != -1:
                        self._caps.host.cpu.parse_str(features)
                except libvirt.VIR_ERR_NO_SUPPORT:
                    # Note(yjiang5): ignore if libvirt has no support
                    pass
        return self._caps

Changed in nova:
status: New → Fix Committed
Revision history for this message
Loganathan Parthipan (parthipan) wrote :

Please link your code commit to this bug. Don't manually change the bug status to 'fix committed'.

Changed in nova:
status: Fix Committed → New
Revision history for this message
Loganathan Parthipan (parthipan) wrote :

I set this bug to 'confirmed' as @Marwan AKIKI has seen the same issue.

Changed in nova:
status: New → Confirmed
Changed in nova:
assignee: nobody → Loganathan Parthipan (parthipan)
Revision history for this message
OpenStack Infra (hudson-openstack) wrote : Fix proposed to nova (master)

Fix proposed to branch: master
Review: https://review.openstack.org/96148

Changed in nova:
status: Confirmed → In Progress
Revision history for this message
Loganathan Parthipan (parthipan) wrote :

I've committed a patch. This fixes my issue of 'libvirtError: XML error: CPU feature `hypervisor' specified more than once' in devtest.

Revision history for this message
Daniel Berrange (berrange) wrote :

This is really a bug in libvirt, not openstack which is fixed in upstream libvirt

commit 802f157e8c7afaf4971b82705f67519939d2da0c
Author: Jiri Denemark <email address hidden>
Date: Mon Jan 27 17:03:55 2014 +0100

    cpu: Fix VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES

    https://bugzilla.redhat.com/show_bug.cgi?id=1049391

    VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES flag for virConnectBaselineCPU
    did not work if the resulting guest CPU would disable some features
    present in its base model. This patch makes sure we won't try to add
    such features twice.

Revision history for this message
Loganathan Parthipan (parthipan) wrote :

@daniel: It's not. I can reproduce this in 1.2.2 with the patch you've mentioned.

The nova bug is that conn.getCapabilites can return named features such as 'hypervisor'. Then when we call baselineCPU the same feature is returned again. Since features is a list being appended to, the get_host_capabilities will have duplicate features. You can reproduce this only when libvirt is run on a guest.

I have checked that VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES works fine and does not return duplicate features.

Revision history for this message
Loganathan Parthipan (parthipan) wrote :

A test program that I used is pasted here:

http://paste.openstack.org/show/81869/

tags: added: libvirt
tags: added: compute
Revision history for this message
OpenStack Infra (hudson-openstack) wrote : Fix merged to nova (master)

Reviewed: https://review.openstack.org/96148
Committed: https://git.openstack.org/cgit/openstack/nova/commit/?id=0f28fbef8bedeafca0bf488b84f783568fefc960
Submitter: Jenkins
Branch: master

commit 0f28fbef8bedeafca0bf488b84f783568fefc960
Author: Loganathan Parthipan <email address hidden>
Date: Wed May 28 11:48:51 2014 +0000

    remove cpu feature duplications in libvirt

    This patch fixes a bug in libvirt driver get_host_capabilities where
    some features can be duplicated. In this patch we use the features returned
    from baselineCPU as the only set of features.

    Change-Id: Ib708e31e5ae14e93b384d2a8933079ca83ca8aaf
    Closes-Bug: #1322702

Changed in nova:
status: In Progress → Fix Committed
Thierry Carrez (ttx)
Changed in nova:
milestone: none → juno-1
status: Fix Committed → Fix Released
Thierry Carrez (ttx)
Changed in nova:
milestone: juno-1 → 2014.2
To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.