Merge "Allow tap interface with multiqueue" into stable/train
This commit is contained in:
commit
e3250402e8
|
@ -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.device_exists', return_value=True)
|
||||||
@mock.patch('nova.privsep.linux_net.set_device_mtu')
|
@mock.patch('nova.privsep.linux_net.set_device_mtu')
|
||||||
@mock.patch('nova.privsep.linux_net.create_tap_dev')
|
@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):
|
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):
|
def test_unplug_tap(self):
|
||||||
d = vif.LibvirtGenericVIFDriver()
|
d = vif.LibvirtGenericVIFDriver()
|
||||||
|
|
|
@ -126,6 +126,24 @@ class LibvirtGenericVIFDriver(object):
|
||||||
return vif['devname']
|
return vif['devname']
|
||||||
return ("nic" + vif['id'])[:network_model.NIC_NAME_LEN]
|
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,
|
def get_base_config(self, instance, mac, image_meta,
|
||||||
inst_type, virt_type, vnic_type, host):
|
inst_type, virt_type, vnic_type, host):
|
||||||
# TODO(sahid): We should rewrite it. This method handles too
|
# 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)
|
conf, mac, model, driver, vhost_queues, rx_queue_size)
|
||||||
return conf
|
return conf
|
||||||
|
|
||||||
# If the user has specified a 'vif_model' against the
|
# if model has already been defined,
|
||||||
# image then honour that model
|
# image_meta contents will override it
|
||||||
if image_meta:
|
model = self.get_vif_model(image_meta=image_meta, vif_model=model)
|
||||||
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 not is_vif_model_valid_for_virt(virt_type, model):
|
if not is_vif_model_valid_for_virt(virt_type, model):
|
||||||
raise exception.UnsupportedHardware(model=model, virt=virt_type)
|
raise exception.UnsupportedHardware(model=model, virt=virt_type)
|
||||||
|
@ -212,10 +223,7 @@ class LibvirtGenericVIFDriver(object):
|
||||||
"""
|
"""
|
||||||
driver = None
|
driver = None
|
||||||
vhost_queues = None
|
vhost_queues = None
|
||||||
if not isinstance(image_meta, objects.ImageMeta):
|
if self._requests_multiqueue(image_meta):
|
||||||
image_meta = objects.ImageMeta.from_dict(image_meta)
|
|
||||||
img_props = image_meta.properties
|
|
||||||
if img_props.get('hw_vif_multiqueue_enabled'):
|
|
||||||
driver = 'vhost'
|
driver = 'vhost'
|
||||||
max_tap_queues = self._get_max_tap_queues()
|
max_tap_queues = self._get_max_tap_queues()
|
||||||
if max_tap_queues:
|
if max_tap_queues:
|
||||||
|
@ -226,6 +234,19 @@ class LibvirtGenericVIFDriver(object):
|
||||||
|
|
||||||
return (driver, vhost_queues)
|
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):
|
def _get_max_tap_queues(self):
|
||||||
# NOTE(kengo.sakai): In kernels prior to 3.0,
|
# NOTE(kengo.sakai): In kernels prior to 3.0,
|
||||||
# multiple queues on a tap interface is not supported.
|
# multiple queues on a tap interface is not supported.
|
||||||
|
@ -690,7 +711,13 @@ class LibvirtGenericVIFDriver(object):
|
||||||
"""Plug a VIF_TYPE_TAP virtual interface."""
|
"""Plug a VIF_TYPE_TAP virtual interface."""
|
||||||
dev = self.get_vif_devname(vif)
|
dev = self.get_vif_devname(vif)
|
||||||
mac = vif['details'].get(network_model.VIF_DETAILS_TAP_MAC_ADDRESS)
|
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')
|
network = vif.get('network')
|
||||||
mtu = network.get_meta('mtu') if network else None
|
mtu = network.get_meta('mtu') if network else None
|
||||||
nova.privsep.linux_net.set_device_mtu(dev, mtu)
|
nova.privsep.linux_net.set_device_mtu(dev, mtu)
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
fixes:
|
||||||
|
- |
|
||||||
|
Addressed an issue that prevented instances using multiqueue feature from
|
||||||
|
being created successfully when their vif_type is TAP.
|
Loading…
Reference in New Issue