summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZuul <zuul@review.opendev.org>2020-10-27 00:55:16 +0000
committerGerrit Code Review <review@openstack.org>2020-10-27 00:55:17 +0000
commit7383d25327fc47a19a664af520d9b12f9e0bd6e4 (patch)
treea1a614f1c0a76a70104ca8aa43a1377a05080747
parentb2c9a4569f59d9911fc31821a2e30a0d75a1edae (diff)
parent8699156d86e0a40b25dd4e22092654b8bc14cccf (diff)
downloadnova-7383d25327fc47a19a664af520d9b12f9e0bd6e4.tar.gz
Merge "Allow tap interface with multiqueue" into stable/stein
-rw-r--r--nova/tests/unit/virt/libvirt/test_vif.py67
-rw-r--r--nova/virt/libvirt/vif.py57
-rw-r--r--releasenotes/notes/bug-1893263-769acadc4b6141d0.yaml5
3 files changed, 111 insertions, 18 deletions
diff --git a/nova/tests/unit/virt/libvirt/test_vif.py b/nova/tests/unit/virt/libvirt/test_vif.py
index 4d4168bcc7..504216ed03 100644
--- a/nova/tests/unit/virt/libvirt/test_vif.py
+++ b/nova/tests/unit/virt/libvirt/test_vif.py
@@ -1125,10 +1125,71 @@ class LibvirtVifTestCase(test.NoDBTestCase):
@mock.patch('nova.privsep.linux_net.device_exists', return_value=True)
@mock.patch('nova.privsep.linux_net.set_device_mtu')
@mock.patch('nova.privsep.linux_net.create_tap_dev')
- def test_plug_tap(self, mock_create_tap_dev, mock_set_mtu,
+ def test_plug_tap_kvm_virtio(self, mock_create_tap_dev, mock_set_mtu,
mock_device_exists):
- d = vif.LibvirtGenericVIFDriver()
- d.plug(self.instance, self.vif_tap)
+
+ d1 = vif.LibvirtGenericVIFDriver()
+ ins = objects.Instance(
+ id=1, uuid='f0000000-0000-0000-0000-000000000001',
+ project_id=723, system_metadata={}
+ )
+ d1.plug(ins, self.vif_tap)
+ mock_create_tap_dev.assert_called_once_with('tap-xxx-yyy-zzz', None,
+ multiqueue=False)
+
+ mock_create_tap_dev.reset_mock()
+
+ d2 = vif.LibvirtGenericVIFDriver()
+ mq_ins = objects.Instance(
+ id=1, uuid='f0000000-0000-0000-0000-000000000001',
+ project_id=723, system_metadata={
+ 'image_hw_vif_multiqueue_enabled': 'True'
+ }
+ )
+ d2.plug(mq_ins, self.vif_tap)
+ mock_create_tap_dev.assert_called_once_with('tap-xxx-yyy-zzz', None,
+ multiqueue=True)
+
+ @mock.patch('nova.privsep.linux_net.device_exists', return_value=True)
+ @mock.patch('nova.privsep.linux_net.set_device_mtu')
+ @mock.patch('nova.privsep.linux_net.create_tap_dev')
+ def test_plug_tap_mq_ignored_virt_type(
+ self, mock_create_tap_dev, mock_set_mtu, mock_device_exists):
+
+ self.flags(use_virtio_for_bridges=True,
+ virt_type='xen',
+ group='libvirt')
+
+ d1 = vif.LibvirtGenericVIFDriver()
+ ins = objects.Instance(
+ id=1, uuid='f0000000-0000-0000-0000-000000000001',
+ project_id=723, system_metadata={
+ 'image_hw_vif_multiqueue_enabled': 'True'
+ }
+ )
+ d1.plug(ins, self.vif_tap)
+ mock_create_tap_dev.assert_called_once_with('tap-xxx-yyy-zzz',
+ None,
+ multiqueue=False)
+
+ @mock.patch('nova.privsep.linux_net.device_exists', return_value=True)
+ @mock.patch('nova.privsep.linux_net.set_device_mtu')
+ @mock.patch('nova.privsep.linux_net.create_tap_dev')
+ def test_plug_tap_mq_ignored_vif_model(
+ self, mock_create_tap_dev, mock_set_mtu, mock_device_exists):
+
+ d1 = vif.LibvirtGenericVIFDriver()
+ ins = objects.Instance(
+ id=1, uuid='f0000000-0000-0000-0000-000000000001',
+ project_id=723, system_metadata={
+ 'image_hw_vif_multiqueue_enabled': 'True',
+ 'image_hw_vif_model': 'e1000',
+ }
+ )
+ d1.plug(ins, self.vif_tap)
+ mock_create_tap_dev.assert_called_once_with('tap-xxx-yyy-zzz',
+ None,
+ multiqueue=False)
def test_unplug_tap(self):
d = vif.LibvirtGenericVIFDriver()
diff --git a/nova/virt/libvirt/vif.py b/nova/virt/libvirt/vif.py
index 57ea1a7382..91e0f4591f 100644
--- a/nova/virt/libvirt/vif.py
+++ b/nova/virt/libvirt/vif.py
@@ -136,6 +136,24 @@ class LibvirtGenericVIFDriver(object):
devname = self.get_vif_devname(vif)
return prefix + devname[3:]
+ def get_vif_model(self, image_meta=None, vif_model=None):
+
+ model = vif_model
+
+ # If the user has specified a 'vif_model' against the
+ # image then honour that model
+ if image_meta:
+ model = osinfo.HardwareProperties(image_meta).network_model
+
+ # If the virt type is KVM/QEMU/VZ(Parallels), then use virtio according
+ # to the global config parameter
+ if (model is None and CONF.libvirt.virt_type in
+ ('kvm', 'qemu', 'parallels') and
+ CONF.libvirt.use_virtio_for_bridges):
+ model = network_model.VIF_MODEL_VIRTIO
+
+ return model
+
def get_base_config(self, instance, mac, image_meta,
inst_type, virt_type, vnic_type, host):
# TODO(sahid): We should rewrite it. This method handles too
@@ -156,16 +174,9 @@ class LibvirtGenericVIFDriver(object):
conf, mac, model, driver, vhost_queues, rx_queue_size)
return conf
- # If the user has specified a 'vif_model' against the
- # image then honour that model
- if image_meta:
- model = osinfo.HardwareProperties(image_meta).network_model
-
- # If the virt type is KVM/QEMU/VZ(Parallels), then use virtio according
- # to the global config parameter
- if (model is None and virt_type in ('kvm', 'qemu', 'parallels') and
- CONF.libvirt.use_virtio_for_bridges):
- model = network_model.VIF_MODEL_VIRTIO
+ # if model has already been defined,
+ # image_meta contents will override it
+ model = self.get_vif_model(image_meta=image_meta, vif_model=model)
# Workaround libvirt bug, where it mistakenly
# enables vhost mode, even for non-KVM guests
@@ -221,10 +232,7 @@ class LibvirtGenericVIFDriver(object):
"""
driver = None
vhost_queues = None
- if not isinstance(image_meta, objects.ImageMeta):
- image_meta = objects.ImageMeta.from_dict(image_meta)
- img_props = image_meta.properties
- if img_props.get('hw_vif_multiqueue_enabled'):
+ if self._requests_multiqueue(image_meta):
driver = 'vhost'
max_tap_queues = self._get_max_tap_queues()
if max_tap_queues:
@@ -235,6 +243,19 @@ class LibvirtGenericVIFDriver(object):
return (driver, vhost_queues)
+ def _requests_multiqueue(self, image_meta):
+ """Check if multiqueue property is set in the image metadata."""
+
+ if not isinstance(image_meta, objects.ImageMeta):
+ image_meta = objects.ImageMeta.from_dict(image_meta)
+
+ img_props = image_meta.properties
+
+ if img_props.get('hw_vif_multiqueue_enabled'):
+ return True
+
+ return False
+
def _get_max_tap_queues(self):
# NOTE(kengo.sakai): In kernels prior to 3.0,
# multiple queues on a tap interface is not supported.
@@ -697,7 +718,13 @@ class LibvirtGenericVIFDriver(object):
"""Plug a VIF_TYPE_TAP virtual interface."""
dev = self.get_vif_devname(vif)
mac = vif['details'].get(network_model.VIF_DETAILS_TAP_MAC_ADDRESS)
- nova.privsep.linux_net.create_tap_dev(dev, mac)
+ image_meta = instance.image_meta
+ vif_model = self.get_vif_model(image_meta=image_meta)
+ # TODO(ganso): explore whether multiqueue works for other vif models
+ # that go through this code path.
+ multiqueue = (self._requests_multiqueue(image_meta) and
+ vif_model == network_model.VIF_MODEL_VIRTIO)
+ nova.privsep.linux_net.create_tap_dev(dev, mac, multiqueue=multiqueue)
network = vif.get('network')
mtu = network.get_meta('mtu') if network else None
nova.privsep.linux_net.set_device_mtu(dev, mtu)
diff --git a/releasenotes/notes/bug-1893263-769acadc4b6141d0.yaml b/releasenotes/notes/bug-1893263-769acadc4b6141d0.yaml
new file mode 100644
index 0000000000..3874489513
--- /dev/null
+++ b/releasenotes/notes/bug-1893263-769acadc4b6141d0.yaml
@@ -0,0 +1,5 @@
+---
+fixes:
+ - |
+ Addressed an issue that prevented instances using multiqueue feature from
+ being created successfully when their vif_type is TAP.