Fix for bug 2140537
If a guest has pinned CPUs the domain XML's <iothreadpin> should have iothread attribute also. Closes-Bug: #2140537 Change-Id: I5c2df747a3fdfbd2ee31d50a3d716a0ccc787e15 Signed-off-by: lajoskatona <lajos.katona@est.tech>
This commit is contained in:
committed by
Lajos Katona
parent
76d796193c
commit
873aee5e95
Vendored
+8
-21
@@ -1233,6 +1233,14 @@ class Domain(object):
|
||||
definition['iothreads'] = iothreads.text
|
||||
|
||||
iothread_pin = tree.find('./cputune/iothreadpin')
|
||||
if iothread_pin is not None and iothread_pin.get('iothread') is None:
|
||||
raise make_libvirtError(
|
||||
libvirtError,
|
||||
"XML error: Missing required attribute 'iothread' "
|
||||
"in element 'iothreadpin'",
|
||||
error_code=VIR_ERR_XML_ERROR,
|
||||
error_domain=VIR_FROM_DOMAIN
|
||||
)
|
||||
if iothread_pin is not None:
|
||||
definition['iothread_pin'] = iothread_pin.get('cpuset')
|
||||
|
||||
@@ -2095,27 +2103,6 @@ class Connection(object):
|
||||
self._emit_lifecycle(dom, VIR_DOMAIN_EVENT_DEFINED, 0)
|
||||
return dom
|
||||
|
||||
# TODO(lajoskatona): Move this validation to defineXML once fix for
|
||||
# bug/2140537 is merged.
|
||||
# This method is only used temporarily from
|
||||
# nova/tests/functional/regressions/test_bug_2140537.py
|
||||
def _defineXMLIOThreads(self, xml):
|
||||
xml_doc = etree.fromstring(xml.encode('utf-8'))
|
||||
iothreadpin = xml_doc.find('./cputune/iothreadpin')
|
||||
|
||||
if iothreadpin is not None and iothreadpin.get('iothread') is None:
|
||||
raise make_libvirtError(
|
||||
libvirtError,
|
||||
"XML error: Missing required attribute 'iothread' "
|
||||
"in element 'iothreadpin'",
|
||||
error_code=VIR_ERR_XML_ERROR,
|
||||
error_domain=VIR_FROM_DOMAIN)
|
||||
|
||||
dom = Domain(connection=self, running=False, transient=False, xml=xml)
|
||||
self._vms[dom.name()] = dom
|
||||
self._emit_lifecycle(dom, VIR_DOMAIN_EVENT_DEFINED, 0)
|
||||
return dom
|
||||
|
||||
def createXML(self, xml, flags):
|
||||
dom = Domain(connection=self, running=True, transient=True, xml=xml)
|
||||
self._vms[dom.name()] = dom
|
||||
|
||||
@@ -22,7 +22,6 @@ in element 'iothreadpin'".
|
||||
"""
|
||||
|
||||
from lxml import etree
|
||||
from unittest import mock
|
||||
|
||||
from nova.tests.fixtures import libvirt as fakelibvirt
|
||||
from nova.tests.functional import integrated_helpers
|
||||
@@ -46,15 +45,6 @@ class TestIOThreadPinningPinnedCPU(
|
||||
ADDITIONAL_FILTERS = ['NUMATopologyFilter']
|
||||
|
||||
def setUp(self):
|
||||
# TODO(lajoskatona): remove this patch when the fix for
|
||||
# bug/2140537 is merged, and the libvirt fixture has the
|
||||
# necessary validation for XML fields for IOThreads.
|
||||
patcher = mock.patch.object(
|
||||
fakelibvirt.Connection, 'defineXML',
|
||||
fakelibvirt.Connection._defineXMLIOThreads)
|
||||
patcher.start()
|
||||
self.addCleanup(patcher.stop)
|
||||
|
||||
super().setUp()
|
||||
self.hostname = self.start_compute(
|
||||
hostname='host1',
|
||||
@@ -91,20 +81,34 @@ class TestIOThreadPinningPinnedCPU(
|
||||
|
||||
# BUG: This fails with libvirt error about missing 'iothread' attribute
|
||||
# The server creation will fail and go to ERROR state
|
||||
# server = self._create_server(
|
||||
# flavor_id=flavor, host='host1', networks='none',
|
||||
# expected_state='ERROR')
|
||||
server = self._create_server(
|
||||
flavor_id=flavor, host='host1', networks='none',
|
||||
expected_state='ERROR')
|
||||
expected_state='ACTIVE')
|
||||
|
||||
# Verify the server is in ERROR state due to the libvirt XML error
|
||||
self.assertEqual('ERROR', server['status'])
|
||||
# self.assertEqual('ERROR', server['status'])
|
||||
|
||||
# Check the fault message contains the libvirt error
|
||||
self.assertIn('Exceeded maximum number of retries',
|
||||
server['fault']['message'])
|
||||
# self.assertIn('Exceeded maximum number of retries',
|
||||
# server['fault']['message'])
|
||||
# Check the logs for the exception
|
||||
self.assertIn("Missing required attribute 'iothread'",
|
||||
self.stdlog.logger.output)
|
||||
self.assertIn("element 'iothreadpin'", self.stdlog.logger.output)
|
||||
# self.assertIn("Missing required attribute 'iothread'",
|
||||
# self.stdlog.logger.output)
|
||||
# self.assertIn("element 'iothreadpin'", self.stdlog.logger.output)
|
||||
|
||||
# Get source XML and verify pinning matches cpu_shared_set
|
||||
conn = self.host.driver._host.get_connection()
|
||||
dom = conn.lookupByUUIDString(server['id'])
|
||||
srv_xml = dom.XMLDesc(0)
|
||||
srv_emulatorpin = self._get_xml_element(
|
||||
srv_xml, './cputune/emulatorpin')
|
||||
srv_iothreadpin = self._get_xml_element(
|
||||
srv_xml, './cputune/iothreadpin')
|
||||
self.assertIsNotNone(srv_emulatorpin)
|
||||
self.assertIsNotNone(srv_iothreadpin)
|
||||
|
||||
def test_iothread_pinning_explicit_numa(self):
|
||||
"""Test iothread pinning with explicit multi-node NUMA topology."""
|
||||
@@ -120,46 +124,46 @@ class TestIOThreadPinningPinnedCPU(
|
||||
flavor = self._create_flavor(vcpu=4, extra_spec=extra_spec)
|
||||
|
||||
# Server should go ACTIVE
|
||||
# server = self._create_server(
|
||||
# flavor_id=flavor, host='host1', networks='none',
|
||||
# expected_state='ACTIVE')
|
||||
server = self._create_server(
|
||||
flavor_id=flavor, host='host1', networks='none',
|
||||
expected_state='ERROR')
|
||||
expected_state='ACTIVE')
|
||||
# server = self._create_server(
|
||||
# flavor_id=flavor, host='host1', networks='none',
|
||||
# expected_state='ERROR')
|
||||
|
||||
# conn = self.host.driver._host.get_connection()
|
||||
# dom = conn.lookupByUUIDString(server['id'])
|
||||
# srv_xml = dom.XMLDesc(0)
|
||||
conn = self.host.driver._host.get_connection()
|
||||
dom = conn.lookupByUUIDString(server['id'])
|
||||
srv_xml = dom.XMLDesc(0)
|
||||
|
||||
# # Should have iothreads element
|
||||
# srv_iothread = self._get_xml_element(srv_xml, './iothreads')
|
||||
# self.assertIsNotNone(srv_iothread)
|
||||
# self.assertEqual('1', srv_iothread.text)
|
||||
# Should have iothreads element
|
||||
srv_iothread = self._get_xml_element(srv_xml, './iothreads')
|
||||
self.assertIsNotNone(srv_iothread)
|
||||
self.assertEqual('1', srv_iothread.text)
|
||||
|
||||
# # Should have emulatorpin and iothreadpin
|
||||
# srv_emulatorpin = self._get_xml_element(
|
||||
# srv_xml, './cputune/emulatorpin')
|
||||
# srv_iothreadpin = self._get_xml_element(
|
||||
# srv_xml, './cputune/iothreadpin')
|
||||
# self.assertIsNotNone(srv_emulatorpin)
|
||||
# self.assertIsNotNone(srv_iothreadpin)
|
||||
# Should have emulatorpin and iothreadpin
|
||||
srv_emulatorpin = self._get_xml_element(
|
||||
srv_xml, './cputune/emulatorpin')
|
||||
srv_iothreadpin = self._get_xml_element(
|
||||
srv_xml, './cputune/iothreadpin')
|
||||
self.assertIsNotNone(srv_emulatorpin)
|
||||
self.assertIsNotNone(srv_iothreadpin)
|
||||
|
||||
# # iothreadpin should have iothread attribute set to 1
|
||||
# self.assertEqual('1', srv_iothreadpin.get('iothread'))
|
||||
# iothreadpin should have iothread attribute set to 1
|
||||
self.assertEqual('1', srv_iothreadpin.get('iothread'))
|
||||
|
||||
# # Both should be pinned to the union of NUMA nodes
|
||||
# self.assertEqual(srv_emulatorpin.get('cpuset'),
|
||||
# srv_iothreadpin.get('cpuset'))
|
||||
# Both should be pinned to the union of NUMA nodes
|
||||
self.assertEqual(srv_emulatorpin.get('cpuset'),
|
||||
srv_iothreadpin.get('cpuset'))
|
||||
|
||||
self.assertEqual('ERROR', server['status'])
|
||||
# self.assertEqual('ERROR', server['status'])
|
||||
|
||||
# Check the fault message contains the libvirt error
|
||||
self.assertIn('Exceeded maximum number of retries',
|
||||
server['fault']['message'])
|
||||
# Check the logs for the exception
|
||||
self.assertIn("Missing required attribute 'iothread'",
|
||||
self.stdlog.logger.output)
|
||||
self.assertIn("element 'iothreadpin'", self.stdlog.logger.output)
|
||||
# # Check the fault message contains the libvirt error
|
||||
# self.assertIn('Exceeded maximum number of retries',
|
||||
# server['fault']['message'])
|
||||
# # Check the logs for the exception
|
||||
# self.assertIn("Missing required attribute 'iothread'",
|
||||
# self.stdlog.logger.output)
|
||||
# self.assertIn("element 'iothreadpin'", self.stdlog.logger.output)
|
||||
|
||||
def test_iothread_pinning_isolated_emulator(self):
|
||||
"""Test iothread pinning with isolated emulator threads policy."""
|
||||
@@ -174,52 +178,52 @@ class TestIOThreadPinningPinnedCPU(
|
||||
}
|
||||
flavor = self._create_flavor(vcpu=2, extra_spec=extra_spec)
|
||||
|
||||
server = self._create_server(
|
||||
flavor_id=flavor, host='host1', networks='none',
|
||||
expected_state='ERROR')
|
||||
# Server should go ACTIVE
|
||||
# server = self._create_server(
|
||||
# flavor_id=flavor, host='host1', networks='none',
|
||||
# expected_state='ACTIVE')
|
||||
# expected_state='ERROR')
|
||||
# Server should go ACTIVE
|
||||
server = self._create_server(
|
||||
flavor_id=flavor, host='host1', networks='none',
|
||||
expected_state='ACTIVE')
|
||||
|
||||
# conn = self.host.driver._host.get_connection()
|
||||
# dom = conn.lookupByUUIDString(server['id'])
|
||||
# srv_xml = dom.XMLDesc(0)
|
||||
conn = self.host.driver._host.get_connection()
|
||||
dom = conn.lookupByUUIDString(server['id'])
|
||||
srv_xml = dom.XMLDesc(0)
|
||||
|
||||
# # Should have iothreads element
|
||||
# srv_iothread = self._get_xml_element(srv_xml, './iothreads')
|
||||
# self.assertIsNotNone(srv_iothread)
|
||||
# self.assertEqual('1', srv_iothread.text)
|
||||
# Should have iothreads element
|
||||
srv_iothread = self._get_xml_element(srv_xml, './iothreads')
|
||||
self.assertIsNotNone(srv_iothread)
|
||||
self.assertEqual('1', srv_iothread.text)
|
||||
|
||||
# # Should have emulatorpin and iothreadpin
|
||||
# srv_emulatorpin = self._get_xml_element(
|
||||
# srv_xml, './cputune/emulatorpin')
|
||||
# srv_iothreadpin = self._get_xml_element(
|
||||
# srv_xml, './cputune/iothreadpin')
|
||||
# self.assertIsNotNone(srv_emulatorpin)
|
||||
# self.assertIsNotNone(srv_iothreadpin)
|
||||
# Should have emulatorpin and iothreadpin
|
||||
srv_emulatorpin = self._get_xml_element(
|
||||
srv_xml, './cputune/emulatorpin')
|
||||
srv_iothreadpin = self._get_xml_element(
|
||||
srv_xml, './cputune/iothreadpin')
|
||||
self.assertIsNotNone(srv_emulatorpin)
|
||||
self.assertIsNotNone(srv_iothreadpin)
|
||||
|
||||
# # iothreadpin should have iothread attribute set to 1
|
||||
# self.assertEqual('1', srv_iothreadpin.get('iothread'))
|
||||
# iothreadpin should have iothread attribute set to 1
|
||||
self.assertEqual('1', srv_iothreadpin.get('iothread'))
|
||||
|
||||
# # Both should be pinned to the same reserved/isolated CPU
|
||||
# self.assertEqual(srv_emulatorpin.get('cpuset'),
|
||||
# srv_iothreadpin.get('cpuset'))
|
||||
# Both should be pinned to the same reserved/isolated CPU
|
||||
self.assertEqual(srv_emulatorpin.get('cpuset'),
|
||||
srv_iothreadpin.get('cpuset'))
|
||||
|
||||
# # Should be pinned to a single CPU (the reserved one)
|
||||
# # With vcpu=2 and isolate policy, one extra CPU is reserved
|
||||
# cpuset = srv_iothreadpin.get('cpuset')
|
||||
# # The cpuset should be a single CPU from cpu_dedicated_set
|
||||
# self.assertIsNotNone(cpuset)
|
||||
self.assertEqual('ERROR', server['status'])
|
||||
# Should be pinned to a single CPU (the reserved one)
|
||||
# With vcpu=2 and isolate policy, one extra CPU is reserved
|
||||
cpuset = srv_iothreadpin.get('cpuset')
|
||||
# The cpuset should be a single CPU from cpu_dedicated_set
|
||||
self.assertIsNotNone(cpuset)
|
||||
# self.assertEqual('ERROR', server['status'])
|
||||
|
||||
# Check the fault message contains the libvirt error
|
||||
self.assertIn('Exceeded maximum number of retries',
|
||||
server['fault']['message'])
|
||||
# Check the logs for the exception
|
||||
self.assertIn("Missing required attribute 'iothread'",
|
||||
self.stdlog.logger.output)
|
||||
self.assertIn("element 'iothreadpin'", self.stdlog.logger.output)
|
||||
# # Check the fault message contains the libvirt error
|
||||
# self.assertIn('Exceeded maximum number of retries',
|
||||
# server['fault']['message'])
|
||||
# # Check the logs for the exception
|
||||
# self.assertIn("Missing required attribute 'iothread'",
|
||||
# self.stdlog.logger.output)
|
||||
# self.assertIn("element 'iothreadpin'", self.stdlog.logger.output)
|
||||
|
||||
def test_iothread_pinning_shared_emulator(self):
|
||||
"""Test iothread pinning with shared emulator threads policy."""
|
||||
@@ -234,48 +238,48 @@ class TestIOThreadPinningPinnedCPU(
|
||||
}
|
||||
flavor = self._create_flavor(vcpu=2, extra_spec=extra_spec)
|
||||
|
||||
server = self._create_server(
|
||||
flavor_id=flavor, host='host1', networks='none',
|
||||
expected_state='ERROR')
|
||||
# Server should go ACTIVE
|
||||
# server = self._create_server(
|
||||
# flavor_id=flavor, host='host1', networks='none',
|
||||
# expected_state='ACTIVE')
|
||||
# expected_state='ERROR')
|
||||
# Server should go ACTIVE
|
||||
server = self._create_server(
|
||||
flavor_id=flavor, host='host1', networks='none',
|
||||
expected_state='ACTIVE')
|
||||
|
||||
# conn = self.host.driver._host.get_connection()
|
||||
# dom = conn.lookupByUUIDString(server['id'])
|
||||
# srv_xml = dom.XMLDesc(0)
|
||||
conn = self.host.driver._host.get_connection()
|
||||
dom = conn.lookupByUUIDString(server['id'])
|
||||
srv_xml = dom.XMLDesc(0)
|
||||
|
||||
# # Should have iothreads element
|
||||
# srv_iothread = self._get_xml_element(srv_xml, './iothreads')
|
||||
# self.assertIsNotNone(srv_iothread)
|
||||
# self.assertEqual('1', srv_iothread.text)
|
||||
# Should have iothreads element
|
||||
srv_iothread = self._get_xml_element(srv_xml, './iothreads')
|
||||
self.assertIsNotNone(srv_iothread)
|
||||
self.assertEqual('1', srv_iothread.text)
|
||||
|
||||
# # Should have emulatorpin and iothreadpin
|
||||
# srv_emulatorpin = self._get_xml_element(
|
||||
# srv_xml, './cputune/emulatorpin')
|
||||
# srv_iothreadpin = self._get_xml_element(
|
||||
# srv_xml, './cputune/iothreadpin')
|
||||
# self.assertIsNotNone(srv_emulatorpin)
|
||||
# self.assertIsNotNone(srv_iothreadpin)
|
||||
# Should have emulatorpin and iothreadpin
|
||||
srv_emulatorpin = self._get_xml_element(
|
||||
srv_xml, './cputune/emulatorpin')
|
||||
srv_iothreadpin = self._get_xml_element(
|
||||
srv_xml, './cputune/iothreadpin')
|
||||
self.assertIsNotNone(srv_emulatorpin)
|
||||
self.assertIsNotNone(srv_iothreadpin)
|
||||
|
||||
# # iothreadpin should have iothread attribute set to 1
|
||||
# self.assertEqual('1', srv_iothreadpin.get('iothread'))
|
||||
# iothreadpin should have iothread attribute set to 1
|
||||
self.assertEqual('1', srv_iothreadpin.get('iothread'))
|
||||
|
||||
# # Both should be pinned to cpu_shared_set (0-1)
|
||||
# self.assertEqual(srv_emulatorpin.get('cpuset'),
|
||||
# srv_iothreadpin.get('cpuset'))
|
||||
# self.assertEqual('0-1', srv_iothreadpin.get('cpuset'))
|
||||
# Both should be pinned to cpu_shared_set (0-1)
|
||||
self.assertEqual(srv_emulatorpin.get('cpuset'),
|
||||
srv_iothreadpin.get('cpuset'))
|
||||
self.assertEqual('0-1', srv_iothreadpin.get('cpuset'))
|
||||
|
||||
self.assertEqual('ERROR', server['status'])
|
||||
# self.assertEqual('ERROR', server['status'])
|
||||
|
||||
# Check the fault message contains the libvirt error
|
||||
self.assertIn('Exceeded maximum number of retries',
|
||||
server['fault']['message'])
|
||||
# Check the logs for the exception
|
||||
self.assertIn("Missing required attribute 'iothread'",
|
||||
self.stdlog.logger.output)
|
||||
self.assertIn("element 'iothreadpin'", self.stdlog.logger.output)
|
||||
# # Check the fault message contains the libvirt error
|
||||
# self.assertIn('Exceeded maximum number of retries',
|
||||
# server['fault']['message'])
|
||||
# # Check the logs for the exception
|
||||
# self.assertIn("Missing required attribute 'iothread'",
|
||||
# self.stdlog.logger.output)
|
||||
# self.assertIn("element 'iothreadpin'", self.stdlog.logger.output)
|
||||
|
||||
def test_iothread_no_pinning(self):
|
||||
# No CPU pinning (shared CPUs only)
|
||||
|
||||
@@ -4054,8 +4054,9 @@ class LibvirtConfigGuestCPUTuneTest(LibvirtConfigBaseTest):
|
||||
cputune.emulatorpin = emu
|
||||
|
||||
iot = config.LibvirtConfigGuestCPUTuneIOThreadPin()
|
||||
iot.iothread = 1
|
||||
iot.cpuset = set([0, 1, 2, 3, 4, 5, 6, 7])
|
||||
cputune.iothreadpin = iot
|
||||
cputune.iothreadpin.append(iot)
|
||||
|
||||
sch0 = config.LibvirtConfigGuestCPUTuneVCPUSched()
|
||||
sch0.vcpus = set([0, 1, 2, 3])
|
||||
@@ -4071,7 +4072,7 @@ class LibvirtConfigGuestCPUTuneTest(LibvirtConfigBaseTest):
|
||||
self.assertXmlEqual("""
|
||||
<cputune>
|
||||
<emulatorpin cpuset="0-7"/>
|
||||
<iothreadpin cpuset="0-7"/>
|
||||
<iothreadpin iothread="1" cpuset="0-7"/>
|
||||
<vcpupin vcpu="0" cpuset="0-1"/>
|
||||
<vcpupin vcpu="1" cpuset="2-3"/>
|
||||
<vcpupin vcpu="2" cpuset="4-5"/>
|
||||
|
||||
@@ -5301,11 +5301,14 @@ class LibvirtConnTestCase(test.NoDBTestCase,
|
||||
cfg = drvr._get_guest_config(instance_ref, [],
|
||||
image_meta, disk_info)
|
||||
|
||||
self.assertIsInstance(cfg.cputune.iothreadpin,
|
||||
self.assertIsInstance(cfg.cputune.iothreadpin, list)
|
||||
self.assertEqual(1, len(cfg.cputune.iothreadpin))
|
||||
self.assertIsInstance(cfg.cputune.iothreadpin[0],
|
||||
vconfig.LibvirtConfigGuestCPUTuneIOThreadPin)
|
||||
self.assertEqual(1, cfg.cputune.iothreadpin[0].iothread)
|
||||
self.assertEqual(cfg.cputune.emulatorpin.cpuset,
|
||||
cfg.cputune.iothreadpin.cpuset)
|
||||
self.assertEqual(set([6]), cfg.cputune.iothreadpin.cpuset)
|
||||
cfg.cputune.iothreadpin[0].cpuset)
|
||||
self.assertEqual(set([6]), cfg.cputune.iothreadpin[0].cpuset)
|
||||
|
||||
@mock.patch.object(host.Host, "_check_machine_type", new=mock.Mock())
|
||||
def test_get_guest_config_iothreadpin_shared_emulator_threads(self):
|
||||
@@ -5356,11 +5359,14 @@ class LibvirtConnTestCase(test.NoDBTestCase,
|
||||
cfg = drvr._get_guest_config(instance_ref, [],
|
||||
image_meta, disk_info)
|
||||
|
||||
self.assertIsInstance(cfg.cputune.iothreadpin,
|
||||
self.assertIsInstance(cfg.cputune.iothreadpin, list)
|
||||
self.assertEqual(1, len(cfg.cputune.iothreadpin))
|
||||
self.assertIsInstance(cfg.cputune.iothreadpin[0],
|
||||
vconfig.LibvirtConfigGuestCPUTuneIOThreadPin)
|
||||
self.assertEqual(1, cfg.cputune.iothreadpin[0].iothread)
|
||||
self.assertEqual(cfg.cputune.emulatorpin.cpuset,
|
||||
cfg.cputune.iothreadpin.cpuset)
|
||||
self.assertEqual(set([1, 2]), cfg.cputune.iothreadpin.cpuset)
|
||||
cfg.cputune.iothreadpin[0].cpuset)
|
||||
self.assertEqual(set([1, 2]), cfg.cputune.iothreadpin[0].cpuset)
|
||||
|
||||
@mock.patch.object(host.Host, "_check_machine_type", new=mock.Mock())
|
||||
def test_get_guest_config_iothreadpin_numa_topology(self):
|
||||
@@ -5407,11 +5413,15 @@ class LibvirtConnTestCase(test.NoDBTestCase,
|
||||
cfg = drvr._get_guest_config(instance_ref, [],
|
||||
image_meta, disk_info)
|
||||
|
||||
self.assertIsInstance(cfg.cputune.iothreadpin,
|
||||
self.assertIsInstance(cfg.cputune.iothreadpin, list)
|
||||
self.assertEqual(1, len(cfg.cputune.iothreadpin))
|
||||
self.assertIsInstance(cfg.cputune.iothreadpin[0],
|
||||
vconfig.LibvirtConfigGuestCPUTuneIOThreadPin)
|
||||
self.assertEqual(1, cfg.cputune.iothreadpin[0].iothread)
|
||||
self.assertEqual(cfg.cputune.emulatorpin.cpuset,
|
||||
cfg.cputune.iothreadpin.cpuset)
|
||||
self.assertEqual(set([0, 1, 2, 3]), cfg.cputune.iothreadpin.cpuset)
|
||||
cfg.cputune.iothreadpin[0].cpuset)
|
||||
self.assertEqual(set([0, 1, 2, 3]),
|
||||
cfg.cputune.iothreadpin[0].cpuset)
|
||||
|
||||
def test_get_guest_config_numa_host_instance_shared_emulthreads_err(
|
||||
self):
|
||||
|
||||
@@ -2675,6 +2675,7 @@ class LibvirtConfigGuestCPUTuneIOThreadPin(LibvirtConfigObject):
|
||||
**kwargs)
|
||||
|
||||
self.cpuset = None
|
||||
self.iothread = None
|
||||
|
||||
def format_dom(self):
|
||||
root = super(LibvirtConfigGuestCPUTuneIOThreadPin, self).format_dom()
|
||||
@@ -2682,6 +2683,8 @@ class LibvirtConfigGuestCPUTuneIOThreadPin(LibvirtConfigObject):
|
||||
if self.cpuset is not None:
|
||||
root.set("cpuset",
|
||||
hardware.format_cpu_spec(self.cpuset))
|
||||
if self.iothread is not None:
|
||||
root.set("iothread", str(self.iothread))
|
||||
|
||||
return root
|
||||
|
||||
@@ -2721,7 +2724,7 @@ class LibvirtConfigGuestCPUTune(LibvirtConfigObject):
|
||||
self.period = None
|
||||
self.vcpupin = []
|
||||
self.emulatorpin = None
|
||||
self.iothreadpin = None
|
||||
self.iothreadpin = []
|
||||
self.vcpusched = []
|
||||
|
||||
def format_dom(self):
|
||||
@@ -2736,8 +2739,11 @@ class LibvirtConfigGuestCPUTune(LibvirtConfigObject):
|
||||
|
||||
if self.emulatorpin is not None:
|
||||
root.append(self.emulatorpin.format_dom())
|
||||
if self.iothreadpin is not None:
|
||||
root.append(self.iothreadpin.format_dom())
|
||||
# Only render <iothreadpin> if fully configured to avoid bug #2140537:
|
||||
# libvirt requires 'iothread' attribute and non-empty 'cpuset'
|
||||
for pin in self.iothreadpin:
|
||||
if pin.iothread is not None and pin.cpuset:
|
||||
root.append(pin.format_dom())
|
||||
for vcpu in self.vcpupin:
|
||||
root.append(vcpu.format_dom())
|
||||
for sched in self.vcpusched:
|
||||
|
||||
@@ -6462,6 +6462,9 @@ class LibvirtDriver(driver.ComputeDriver):
|
||||
|
||||
return emulatorpin_cpuset
|
||||
|
||||
def _get_guest_iothread(self):
|
||||
return 1
|
||||
|
||||
def _get_guest_numa_config(self, instance_numa_topology, flavor,
|
||||
image_meta):
|
||||
"""Returns the config objects for the guest NUMA specs.
|
||||
@@ -6532,9 +6535,6 @@ class LibvirtDriver(driver.ComputeDriver):
|
||||
guest_cpu_tune.emulatorpin = (
|
||||
vconfig.LibvirtConfigGuestCPUTuneEmulatorPin())
|
||||
guest_cpu_tune.emulatorpin.cpuset = set([])
|
||||
guest_cpu_tune.iothreadpin = (
|
||||
vconfig.LibvirtConfigGuestCPUTuneIOThreadPin())
|
||||
guest_cpu_tune.iothreadpin.cpuset = set([])
|
||||
|
||||
# Init NUMATune configuration
|
||||
guest_numa_tune = vconfig.LibvirtConfigGuestNUMATune()
|
||||
@@ -6578,7 +6578,14 @@ class LibvirtDriver(driver.ComputeDriver):
|
||||
# both emulator and iothreads are pinned to cores other
|
||||
# than the instance's cores to support realtime cpus.
|
||||
guest_cpu_tune.emulatorpin.cpuset.update(emu_pin_cpuset)
|
||||
guest_cpu_tune.iothreadpin.cpuset.update(emu_pin_cpuset)
|
||||
|
||||
# Create iothreadpin entries after processing all cells
|
||||
# Use the same cpuset as emulatorpin
|
||||
for iothread_id in range(self._get_guest_iothread()):
|
||||
iothread_pin = vconfig.LibvirtConfigGuestCPUTuneIOThreadPin()
|
||||
iothread_pin.iothread = iothread_id + 1
|
||||
iothread_pin.cpuset = guest_cpu_tune.emulatorpin.cpuset
|
||||
guest_cpu_tune.iothreadpin.append(iothread_pin)
|
||||
|
||||
# TODO(berrange) When the guest has >1 NUMA node, it will
|
||||
# span multiple host NUMA nodes. By pinning emulator threads
|
||||
@@ -7609,8 +7616,9 @@ class LibvirtDriver(driver.ComputeDriver):
|
||||
self._set_features(guest, instance.os_type, image_meta, flavor)
|
||||
self._set_clock(guest, instance.os_type, image_meta)
|
||||
|
||||
# Set IOThreads to 1 for everybody
|
||||
guest.iothreads = 1
|
||||
# Set IOThreads to the same value for everybody,
|
||||
# returned by _get_guest_iothread
|
||||
guest.iothreads = self._get_guest_iothread()
|
||||
|
||||
storage_configs = self._get_guest_storage_config(context,
|
||||
instance, image_meta, disk_info, rescue, block_device_info,
|
||||
|
||||
Reference in New Issue
Block a user