summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRodrigo Barbieri <rodrigo.barbieri2010@gmail.com>2020-08-27 17:20:19 -0300
committerRodrigo Barbieri <rodrigo.barbieri2010@gmail.com>2020-10-13 11:23:57 -0300
commit8699156d86e0a40b25dd4e22092654b8bc14cccf (patch)
tree9ddd9f19068639372aa50a6afefa2d02c04cf970
parentc425f7f81baaaca238f029add30e9c02577850e0 (diff)
downloadnova-8699156d86e0a40b25dd4e22092654b8bc14cccf.tar.gz
Allow tap interface with multiqueue
When vif_type="tap" (such as when using calico), attempting to create an instance using an image that has the property hw_vif_multiqueue_enabled=True fails, because the interface is always being created without multiqueue flags. This change checks if the property is defined and passes the multiqueue parameter to create the tap interface accordingly. In case the multiqueue parameter is passed but the vif_model is not virtio (or unspecified), the old behavior is maintained. Conflicts: nova/virt/libvirt/vif.py NOTE: The conflict is for not having change Iab16a15a5f141a7f7aae4172b092c50ee7964597 in stable/stein. Change-Id: I0307c43dcd0cace1620d2ac75925651d4ee2e96c Closes-bug: #1893263 (cherry picked from commit 84cfc8e9ab1396ec17abcfc9646c7d40f1d966ae) (cherry picked from commit a69845f3732843ee1451b2e4ebf547d9801e898d) (cherry picked from commit 750655c19daf4e8d0dcf35d3b1cab5e6d8ac69ba)
-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.