diff -Nru nova-19.3.1/debian/changelog nova-19.3.1/debian/changelog --- nova-19.3.1/debian/changelog 2020-10-01 13:31:33.000000000 +0000 +++ nova-19.3.1/debian/changelog 2020-10-26 21:56:01.000000000 +0000 @@ -1,3 +1,9 @@ +nova (2:19.3.1-0ubuntu1~cloud1) bionic; urgency=medium + + * d/p/lp1893263.patch: Allow tap interface with multiqueue (LP: #1893263). + + -- Rodrigo Barbieri Mon, 26 Oct 2020 21:56:01 +0000 + nova (2:19.3.1-0ubuntu1~cloud0) bionic-stein; urgency=medium * New stable point release for OpenStack Stein (LP: #1896478). diff -Nru nova-19.3.1/debian/patches/lp1893263.patch nova-19.3.1/debian/patches/lp1893263.patch --- nova-19.3.1/debian/patches/lp1893263.patch 1970-01-01 00:00:00.000000000 +0000 +++ nova-19.3.1/debian/patches/lp1893263.patch 2020-10-26 21:55:34.000000000 +0000 @@ -0,0 +1,226 @@ +From a90bd8740b7796ddc1caed193694cf5d1b18876a Mon Sep 17 00:00:00 2001 +From: Rodrigo Barbieri +Date: Thu, 27 Aug 2020 17:20:19 -0300 +Subject: [PATCH] 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) +--- + nova/tests/unit/virt/libvirt/test_vif.py | 67 ++++++++++++++++++- + nova/virt/libvirt/vif.py | 57 +++++++++++----- + .../notes/bug-1893263-769acadc4b6141d0.yaml | 5 ++ + 3 files changed, 111 insertions(+), 18 deletions(-) + create mode 100644 releasenotes/notes/bug-1893263-769acadc4b6141d0.yaml + +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. +-- +2.17.1 + diff -Nru nova-19.3.1/debian/patches/series nova-19.3.1/debian/patches/series --- nova-19.3.1/debian/patches/series 2020-10-01 13:31:33.000000000 +0000 +++ nova-19.3.1/debian/patches/series 2020-10-26 21:55:34.000000000 +0000 @@ -3,3 +3,4 @@ skip-ssl-tests.patch arm-console-patch.patch revert-generalize-db-conf-group-copying.patch +lp1893263.patch