summaryrefslogtreecommitdiff
path: root/nova
diff options
context:
space:
mode:
authorJenkins <jenkins@review.openstack.org>2015-01-17 00:34:18 +0000
committerGerrit Code Review <review@openstack.org>2015-01-17 00:34:18 +0000
commit5903ce2e4db6897e43fcad9e7d38e2d909c42c1a (patch)
tree4cf322021ca74947c6f885d23852bda51681df19 /nova
parentb4a809240cd8f6ab33468f95c701348c9b66f6d3 (diff)
parentcc5a473cfad54b5a38f5ed8c2d3d930ea6ebb421 (diff)
downloadnova-5903ce2e4db6897e43fcad9e7d38e2d909c42c1a.tar.gz
Merge "libvirt: move capabilities helper into host.py"
Diffstat (limited to 'nova')
-rw-r--r--nova/tests/unit/virt/libvirt/fakelibvirt.py15
-rw-r--r--nova/tests/unit/virt/libvirt/test_driver.py143
-rw-r--r--nova/tests/unit/virt/libvirt/test_host.py83
-rw-r--r--nova/virt/libvirt/driver.py43
-rw-r--r--nova/virt/libvirt/host.py33
5 files changed, 160 insertions, 157 deletions
diff --git a/nova/tests/unit/virt/libvirt/fakelibvirt.py b/nova/tests/unit/virt/libvirt/fakelibvirt.py
index 1aebc0b49b..10f499f07a 100644
--- a/nova/tests/unit/virt/libvirt/fakelibvirt.py
+++ b/nova/tests/unit/virt/libvirt/fakelibvirt.py
@@ -1050,8 +1050,21 @@ class Connection(object):
def baselineCPU(self, cpu, flag):
"""Add new libvirt API."""
return """<cpu mode='custom' match='exact'>
- <model fallback='allow'>Westmere</model>
+ <model>Penryn</model>
<vendor>Intel</vendor>
+ <feature name='xtpr'/>
+ <feature name='tm2'/>
+ <feature name='est'/>
+ <feature name='vmx'/>
+ <feature name='ds_cpl'/>
+ <feature name='monitor'/>
+ <feature name='pbe'/>
+ <feature name='tm'/>
+ <feature name='ht'/>
+ <feature name='ss'/>
+ <feature name='acpi'/>
+ <feature name='ds'/>
+ <feature name='vme'/>
<feature policy='require' name='aes'/>
</cpu>"""
diff --git a/nova/tests/unit/virt/libvirt/test_driver.py b/nova/tests/unit/virt/libvirt/test_driver.py
index cf75814417..31b95fbeeb 100644
--- a/nova/tests/unit/virt/libvirt/test_driver.py
+++ b/nova/tests/unit/virt/libvirt/test_driver.py
@@ -917,8 +917,7 @@ class LibvirtConnTestCase(test.NoDBTestCase):
@mock.patch.object(libvirt, 'registerErrorHandler',
side_effect=fake_registerErrorHandler)
- @mock.patch.object(libvirt_driver.LibvirtDriver,
- '_get_host_capabilities',
+ @mock.patch.object(host.Host, "get_capabilities",
side_effect=fake_get_host_capabilities)
def test_init_host(get_host_capabilities, register_error_handler):
conn = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True)
@@ -958,89 +957,6 @@ class LibvirtConnTestCase(test.NoDBTestCase):
# our stub method is called which asserts the password is scrubbed
self.assertTrue(debug_mock.called)
- def test_cpu_features_bug_1217630(self):
- conn = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True)
-
- # Test old version of libvirt, it shouldn't see the `aes' feature
- with mock.patch('nova.virt.libvirt.driver.libvirt') as mock_libvirt:
- del mock_libvirt.VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES
- caps = conn._get_host_capabilities()
- self.assertNotIn('aes', [x.name for x in caps.host.cpu.features])
-
- # Test new verion of libvirt, should find the `aes' feature
- with mock.patch('nova.virt.libvirt.driver.libvirt') as mock_libvirt:
- mock_libvirt['VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES'] = 1
- # Cleanup the capabilities cache firstly
- conn._caps = None
- caps = conn._get_host_capabilities()
- self.assertIn('aes', [x.name for x in caps.host.cpu.features])
-
- def test_cpu_features_are_not_duplicated(self):
- conn = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True)
-
- # Test old version of libvirt. Should return single 'hypervisor'
- with mock.patch('nova.virt.libvirt.driver.libvirt') as mock_libvirt:
- del mock_libvirt.VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES
- caps = conn._get_host_capabilities()
- cnt = [x.name for x in caps.host.cpu.features].count('hypervisor')
- self.assertEqual(1, cnt)
-
- # Test new version of libvirt. Should still return single 'hypervisor'
- with mock.patch('nova.virt.libvirt.driver.libvirt') as mock_libvirt:
- mock_libvirt['VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES'] = 1
- # Cleanup the capabilities cache firstly
- conn._caps = None
- caps = conn._get_host_capabilities()
- cnt = [x.name for x in caps.host.cpu.features].count('hypervisor')
- self.assertEqual(1, cnt)
-
- def test_baseline_cpu_not_supported(self):
- conn = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True)
-
- # `mock` has trouble stubbing attributes that don't exist yet, so
- # fallback to plain-Python attribute setting/deleting
- cap_str = 'VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES'
- if not hasattr(libvirt_driver.libvirt, cap_str):
- setattr(libvirt_driver.libvirt, cap_str, True)
- self.addCleanup(delattr, libvirt_driver.libvirt, cap_str)
-
- # Handle just the NO_SUPPORT error
- not_supported_exc = fakelibvirt.make_libvirtError(
- libvirt.libvirtError,
- 'this function is not supported by the connection driver:'
- ' virConnectBaselineCPU',
- error_code=libvirt.VIR_ERR_NO_SUPPORT)
-
- with mock.patch.object(conn._conn, 'baselineCPU',
- side_effect=not_supported_exc):
- caps = conn._get_host_capabilities()
- self.assertEqual(vconfig.LibvirtConfigCaps, type(caps))
- self.assertNotIn('aes', [x.name for x in caps.host.cpu.features])
-
- # Clear cached result so we can test again...
- conn._caps = None
-
- # Other errors should not be caught
- other_exc = fakelibvirt.make_libvirtError(
- libvirt.libvirtError,
- 'other exc',
- error_code=libvirt.VIR_ERR_NO_DOMAIN)
-
- with mock.patch.object(conn._conn, 'baselineCPU',
- side_effect=other_exc):
- self.assertRaises(libvirt.libvirtError,
- conn._get_host_capabilities)
-
- def test_lxc_get_host_capabilities_failed(self):
- conn = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True)
-
- with mock.patch.object(conn._conn, 'baselineCPU', return_value=-1):
- setattr(libvirt, 'VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES', 1)
- caps = conn._get_host_capabilities()
- delattr(libvirt, 'VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES')
- self.assertEqual(vconfig.LibvirtConfigCaps, type(caps))
- self.assertNotIn('aes', [x.name for x in caps.host.cpu.features])
-
@mock.patch.object(time, "time")
def test_get_guest_config(self, time_mock):
time_mock.return_value = 1234567.89
@@ -1220,8 +1136,8 @@ class LibvirtConnTestCase(test.NoDBTestCase):
with contextlib.nested(
mock.patch.object(host.Host, 'has_min_version',
return_value=True),
- mock.patch.object(
- conn, "_get_host_capabilities", return_value=caps),
+ mock.patch.object(host.Host, "get_capabilities",
+ return_value=caps),
mock.patch.object(
random, 'choice', side_effect=lambda cells: cells[0])):
cfg = conn._get_guest_config(instance_ref, [], {}, disk_info)
@@ -1248,8 +1164,8 @@ class LibvirtConnTestCase(test.NoDBTestCase):
instance_ref)
with contextlib.nested(
- mock.patch.object(
- conn, "_get_host_capabilities", return_value=caps),
+ mock.patch.object(host.Host, "get_capabilities",
+ return_value=caps),
mock.patch.object(
hardware, 'get_vcpu_pin_set', return_value=set([3])),
mock.patch.object(random, 'choice')
@@ -1319,8 +1235,8 @@ class LibvirtConnTestCase(test.NoDBTestCase):
with contextlib.nested(
mock.patch.object(host.Host, 'has_min_version',
return_value=True),
- mock.patch.object(
- conn, "_get_host_capabilities", return_value=caps),
+ mock.patch.object(host.Host, "get_capabilities",
+ return_value=caps),
mock.patch.object(
hardware, 'get_vcpu_pin_set', return_value=set([2, 3])),
mock.patch.object(
@@ -1365,8 +1281,8 @@ class LibvirtConnTestCase(test.NoDBTestCase):
return_value=instance_topology),
mock.patch.object(host.Host, 'has_min_version',
return_value=True),
- mock.patch.object(
- conn, "_get_host_capabilities", return_value=caps)):
+ mock.patch.object(host.Host, "get_capabilities",
+ return_value=caps)):
cfg = conn._get_guest_config(instance_ref, [], {}, disk_info)
self.assertIsNone(cfg.cpuset)
self.assertEqual(0, len(cfg.cputune.vcpupin))
@@ -1412,8 +1328,8 @@ class LibvirtConnTestCase(test.NoDBTestCase):
return_value=instance_topology),
mock.patch.object(host.Host, 'has_min_version',
return_value=True),
- mock.patch.object(
- conn, "_get_host_capabilities", return_value=caps),
+ mock.patch.object(host.Host, "get_capabilities",
+ return_value=caps),
mock.patch.object(
hardware, 'get_vcpu_pin_set',
return_value=set([2, 3, 4, 5]))
@@ -1489,8 +1405,8 @@ class LibvirtConnTestCase(test.NoDBTestCase):
return_value=instance_topology),
mock.patch.object(host.Host, 'has_min_version',
return_value=True),
- mock.patch.object(
- conn, "_get_host_capabilities", return_value=caps),
+ mock.patch.object(host.Host, "get_capabilities",
+ return_value=caps),
):
cfg = conn._get_guest_config(instance_ref, [], {}, disk_info)
self.assertIsNone(cfg.cpuset)
@@ -2483,8 +2399,7 @@ class LibvirtConnTestCase(test.NoDBTestCase):
caps.host.cpu = cpu
return caps
- self.stubs.Set(libvirt_driver.LibvirtDriver,
- "_get_host_capabilities",
+ self.stubs.Set(host.Host, "get_capabilities",
get_host_capabilities_stub)
def _stub_guest_cpu_config_arch(self, cpu_arch):
@@ -3621,8 +3536,7 @@ class LibvirtConnTestCase(test.NoDBTestCase):
disk_info = blockinfo.get_disk_info(CONF.libvirt.virt_type,
instance_ref)
- self.stubs.Set(libvirt_driver.LibvirtDriver,
- "_get_host_capabilities",
+ self.stubs.Set(host.Host, "get_capabilities",
get_host_capabilities_stub)
conn = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True)
@@ -3653,8 +3567,7 @@ class LibvirtConnTestCase(test.NoDBTestCase):
disk_info = blockinfo.get_disk_info(CONF.libvirt.virt_type,
instance_ref)
- self.stubs.Set(libvirt_driver.LibvirtDriver,
- "_get_host_capabilities",
+ self.stubs.Set(host.Host, "get_capabilities",
get_host_capabilities_stub)
conn = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True)
@@ -8651,8 +8564,7 @@ class LibvirtConnTestCase(test.NoDBTestCase):
return caps
- self.stubs.Set(libvirt_driver.LibvirtDriver,
- '_get_host_capabilities',
+ self.stubs.Set(host.Host, "get_capabilities",
get_host_capabilities_stub)
want = {"vendor": "AMD",
@@ -8845,8 +8757,8 @@ class LibvirtConnTestCase(test.NoDBTestCase):
with contextlib.nested(
mock.patch.object(host.Host, 'has_min_version',
return_value=True),
- mock.patch.object(
- conn, '_get_host_capabilities', return_value=caps),
+ mock.patch.object(host.Host, "get_capabilities",
+ return_value=caps),
mock.patch.object(
hardware, 'get_vcpu_pin_set', return_value=set([0, 1, 3]))
):
@@ -8873,7 +8785,7 @@ class LibvirtConnTestCase(test.NoDBTestCase):
conn = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False)
with contextlib.nested(
mock.patch.object(host.Host, 'has_min_version', return_value=True),
- mock.patch.object(conn, '_get_host_capabilities',
+ mock.patch.object(host.Host, "get_capabilities",
return_value=caps)
) as (has_min_version, get_caps):
self.assertIsNone(conn._get_host_numa_topology())
@@ -9606,8 +9518,7 @@ Active: 8381604 kB
return caps
- self.stubs.Set(libvirt_driver.LibvirtDriver,
- '_get_host_capabilities',
+ self.stubs.Set(host.Host, "get_capabilities",
get_host_capabilities_stub)
want = [(arch.X86_64, 'kvm', 'hvm'),
@@ -10235,21 +10146,15 @@ Active: 8381604 kB
network_info = _fake_network_info(self.stubs, 1)
self.create_fake_libvirt_mock(getLibVersion=fake_getLibVersion,
getCapabilities=fake_getCapabilities,
- getVersion=lambda: 1005001)
+ getVersion=lambda: 1005001,
+ listDefinedDomains=lambda: [],
+ baselineCPU=fake_baselineCPU)
instance_ref = self.test_instance
instance_ref['image_ref'] = 123456 # we send an int to test sha1 call
instance = objects.Instance(**instance_ref)
flavor = instance.get_flavor()
flavor.extra_specs = {}
- self.mox.StubOutWithMock(libvirt_driver.LibvirtDriver, '_conn')
- libvirt_driver.LibvirtDriver._conn.listDefinedDomains = lambda: []
- libvirt_driver.LibvirtDriver._conn.getCapabilities = \
- fake_getCapabilities
- libvirt_driver.LibvirtDriver._conn.getVersion = lambda: 1005001
- libvirt_driver.LibvirtDriver._conn.defineXML = fake_defineXML
- libvirt_driver.LibvirtDriver._conn.baselineCPU = fake_baselineCPU
-
self.mox.ReplayAll()
conn = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False)
diff --git a/nova/tests/unit/virt/libvirt/test_host.py b/nova/tests/unit/virt/libvirt/test_host.py
index 04b2bccfa0..21d72d8397 100644
--- a/nova/tests/unit/virt/libvirt/test_host.py
+++ b/nova/tests/unit/virt/libvirt/test_host.py
@@ -25,6 +25,7 @@ from nova import objects
from nova import test
from nova.tests.unit.virt.libvirt import fakelibvirt
from nova.virt import event
+from nova.virt.libvirt import config as vconfig
from nova.virt.libvirt import host
try:
@@ -551,3 +552,85 @@ class HostTestCase(test.NoDBTestCase):
self.assertEqual(doms[1].name(), vm1.name())
self.assertEqual(doms[2].name(), vm2.name())
mock_list.assert_called_with(True)
+
+ def test_cpu_features_bug_1217630(self):
+ self.host.get_connection()
+
+ # Test old version of libvirt, it shouldn't see the `aes' feature
+ with mock.patch('nova.virt.libvirt.host.libvirt') as mock_libvirt:
+ del mock_libvirt.VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES
+ caps = self.host.get_capabilities()
+ self.assertNotIn('aes', [x.name for x in caps.host.cpu.features])
+
+ # Cleanup the capabilities cache firstly
+ self.host._caps = None
+
+ # Test new version of libvirt, should find the `aes' feature
+ with mock.patch('nova.virt.libvirt.host.libvirt') as mock_libvirt:
+ mock_libvirt['VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES'] = 1
+ caps = self.host.get_capabilities()
+ self.assertIn('aes', [x.name for x in caps.host.cpu.features])
+
+ def test_cpu_features_are_not_duplicated(self):
+ self.host.get_connection()
+
+ # Test old version of libvirt. Should return single 'hypervisor'
+ with mock.patch('nova.virt.libvirt.host.libvirt') as mock_libvirt:
+ del mock_libvirt.VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES
+ caps = self.host.get_capabilities()
+ cnt = [x.name for x in caps.host.cpu.features].count('xtpr')
+ self.assertEqual(1, cnt)
+
+ # Cleanup the capabilities cache firstly
+ self.host._caps = None
+
+ # Test new version of libvirt. Should still return single 'hypervisor'
+ with mock.patch('nova.virt.libvirt.host.libvirt') as mock_libvirt:
+ mock_libvirt['VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES'] = 1
+ caps = self.host.get_capabilities()
+ cnt = [x.name for x in caps.host.cpu.features].count('xtpr')
+ self.assertEqual(1, cnt)
+
+ def test_baseline_cpu_not_supported(self):
+ # `mock` has trouble stubbing attributes that don't exist yet, so
+ # fallback to plain-Python attribute setting/deleting
+ cap_str = 'VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES'
+ if not hasattr(host.libvirt, cap_str):
+ setattr(host.libvirt, cap_str, True)
+ self.addCleanup(delattr, host.libvirt, cap_str)
+
+ # Handle just the NO_SUPPORT error
+ not_supported_exc = fakelibvirt.make_libvirtError(
+ libvirt.libvirtError,
+ 'this function is not supported by the connection driver:'
+ ' virConnectBaselineCPU',
+ error_code=libvirt.VIR_ERR_NO_SUPPORT)
+
+ with mock.patch.object(fakelibvirt.virConnect, 'baselineCPU',
+ side_effect=not_supported_exc):
+ caps = self.host.get_capabilities()
+ self.assertEqual(vconfig.LibvirtConfigCaps, type(caps))
+ self.assertNotIn('aes', [x.name for x in caps.host.cpu.features])
+
+ # Clear cached result so we can test again...
+ self.host._caps = None
+
+ # Other errors should not be caught
+ other_exc = fakelibvirt.make_libvirtError(
+ libvirt.libvirtError,
+ 'other exc',
+ error_code=libvirt.VIR_ERR_NO_DOMAIN)
+
+ with mock.patch.object(fakelibvirt.virConnect, 'baselineCPU',
+ side_effect=other_exc):
+ self.assertRaises(libvirt.libvirtError,
+ self.host.get_capabilities)
+
+ def test_lxc_get_host_capabilities_failed(self):
+ with mock.patch.object(fakelibvirt.virConnect, 'baselineCPU',
+ return_value=-1):
+ setattr(libvirt, 'VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES', 1)
+ caps = self.host.get_capabilities()
+ delattr(libvirt, 'VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES')
+ self.assertEqual(vconfig.LibvirtConfigCaps, type(caps))
+ self.assertNotIn('aes', [x.name for x in caps.host.cpu.features])
diff --git a/nova/virt/libvirt/driver.py b/nova/virt/libvirt/driver.py
index f4223a3128..9d4bb95f09 100644
--- a/nova/virt/libvirt/driver.py
+++ b/nova/virt/libvirt/driver.py
@@ -495,7 +495,7 @@ class LibvirtDriver(driver.ComputeDriver):
unknown. Currently, only qemu or kvm on intel 32- or 64-bit systems
is tested upstream.
"""
- caps = self._get_host_capabilities()
+ caps = self._host.get_capabilities()
hostarch = caps.host.cpu.arch
if (CONF.libvirt.virt_type not in ('qemu', 'kvm') or
hostarch not in (arch.I686, arch.X86_64)):
@@ -2991,37 +2991,6 @@ class LibvirtDriver(driver.ComputeDriver):
'due to an unexpected exception.'), CONF.host,
exc_info=True)
- 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:
- cpu = vconfig.LibvirtConfigCPU()
- cpu.parse_str(features)
- self._caps.host.cpu.features = cpu.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
-
def _get_guest_cpu_model_config(self):
mode = CONF.libvirt.cpu_mode
model = CONF.libvirt.cpu_model
@@ -3204,7 +3173,7 @@ class LibvirtDriver(driver.ComputeDriver):
This is typically from the SMBIOS data, unless it has
been overridden in /etc/libvirt/libvirtd.conf
"""
- caps = self._get_host_capabilities()
+ caps = self._host.get_capabilities()
return caps.host.uuid
def _get_host_sysinfo_serial_os(self):
@@ -3820,7 +3789,7 @@ class LibvirtDriver(driver.ComputeDriver):
if guest.os_type is None:
guest.os_type = self._get_guest_os_type(virt_type)
- caps = self._get_host_capabilities()
+ caps = self._host.get_capabilities()
if virt_type == "xen":
if guest.os_type == vm_mode.HVM:
@@ -4476,7 +4445,7 @@ class LibvirtDriver(driver.ComputeDriver):
:returns: List of tuples describing instance capabilities
"""
- caps = self._get_host_capabilities()
+ caps = self._host.get_capabilities()
instance_caps = list()
for g in caps.guests:
for dt in g.domtype:
@@ -4498,7 +4467,7 @@ class LibvirtDriver(driver.ComputeDriver):
"""
- caps = self._get_host_capabilities()
+ caps = self._host.get_capabilities()
cpu_info = dict()
cpu_info['arch'] = caps.host.cpu.arch
@@ -4624,7 +4593,7 @@ class LibvirtDriver(driver.ComputeDriver):
if not self._host.has_min_version(MIN_LIBVIRT_NUMA_TOPOLOGY_VERSION):
return
- caps = self._get_host_capabilities()
+ caps = self._host.get_capabilities()
topology = caps.host.topology
if topology is None or not topology.cells:
diff --git a/nova/virt/libvirt/host.py b/nova/virt/libvirt/host.py
index 037197c131..9f8e45bea7 100644
--- a/nova/virt/libvirt/host.py
+++ b/nova/virt/libvirt/host.py
@@ -48,6 +48,7 @@ from nova.openstack.common import log as logging
from nova import rpc
from nova import utils
from nova.virt import event as virtevent
+from nova.virt.libvirt import config as vconfig
libvirt = None
@@ -77,6 +78,7 @@ class Host(object):
self._conn_event_handler = conn_event_handler
self._lifecycle_event_handler = lifecycle_event_handler
self._skip_list_all_domains = False
+ self._caps = None
self._wrapped_conn = None
self._wrapped_conn_lock = threading.Lock()
@@ -573,3 +575,34 @@ class Host(object):
doms.append(dom)
return doms
+
+ def get_capabilities(self):
+ """Returns an instance of config.LibvirtConfigCaps representing
+ the capabilities of the host.
+ """
+ if not self._caps:
+ xmlstr = self.get_connection().getCapabilities()
+ self._caps = vconfig.LibvirtConfigCaps()
+ self._caps.parse_str(xmlstr)
+ if hasattr(libvirt, 'VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES'):
+ try:
+ features = self.get_connection().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:
+ cpu = vconfig.LibvirtConfigCPU()
+ cpu.parse_str(features)
+ self._caps.host.cpu.features = cpu.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