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.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()
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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