Merge "Allow tap interface with multiqueue" into stable/train

This commit is contained in:
Zuul 2020-10-16 03:40:45 +00:00 committed by Gerrit Code Review
commit e3250402e8
3 changed files with 111 additions and 18 deletions

View File

@ -1123,10 +1123,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()

View File

@ -126,6 +126,24 @@ class LibvirtGenericVIFDriver(object):
return vif['devname']
return ("nic" + vif['id'])[:network_model.NIC_NAME_LEN]
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
@ -146,16 +164,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)
if not is_vif_model_valid_for_virt(virt_type, model):
raise exception.UnsupportedHardware(model=model, virt=virt_type)
@ -212,10 +223,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:
@ -226,6 +234,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.
@ -690,7 +711,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)

View File

@ -0,0 +1,5 @@
---
fixes:
- |
Addressed an issue that prevented instances using multiqueue feature from
being created successfully when their vif_type is TAP.