summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--nova/tests/unit/api/openstack/compute/test_services.py19
-rw-r--r--nova/tests/unit/console/test_websocketproxy.py27
-rw-r--r--nova/tests/unit/storage/test_rbd.py42
-rw-r--r--nova/tests/unit/virt/libvirt/test_vif.py48
-rw-r--r--nova/virt/libvirt/vif.py3
-rw-r--r--releasenotes/notes/bug-1939604-547c729b7741831b.yaml5
6 files changed, 96 insertions, 48 deletions
diff --git a/nova/tests/unit/api/openstack/compute/test_services.py b/nova/tests/unit/api/openstack/compute/test_services.py
index 170b39f208..07acbaab16 100644
--- a/nova/tests/unit/api/openstack/compute/test_services.py
+++ b/nova/tests/unit/api/openstack/compute/test_services.py
@@ -701,6 +701,25 @@ class ServicesTestV21(test.TestCase):
mock_get_compute_nodes.assert_called_once_with(
self.req.environ['nova.context'], compute.host)
+ @mock.patch(
+ 'nova.objects.ComputeNodeList.get_all_by_host',
+ side_effect=exception.ComputeHostNotFound(host='fake-compute-host'))
+ def test_services_delete_compute_host_not_found(
+ self, mock_get_all_by_host):
+ compute = objects.Service(self.ctxt,
+ **{'host': 'fake-compute-host',
+ 'binary': 'nova-compute',
+ 'topic': 'compute',
+ 'report_count': 0})
+ compute.create()
+ # FIXME(artom) Until bug 1860312 is fixed, the ComputeHostNotFound
+ # error will get bubbled up to the API as an error 500.
+ self.assertRaises(
+ webob.exc.HTTPInternalServerError,
+ self.controller.delete, self.req, compute.id)
+ mock_get_all_by_host.assert_called_with(
+ self.req.environ['nova.context'], 'fake-compute-host')
+
def test_services_delete_not_found(self):
self.assertRaises(webob.exc.HTTPNotFound,
diff --git a/nova/tests/unit/console/test_websocketproxy.py b/nova/tests/unit/console/test_websocketproxy.py
index 4ed2d2d4dc..11561f4c53 100644
--- a/nova/tests/unit/console/test_websocketproxy.py
+++ b/nova/tests/unit/console/test_websocketproxy.py
@@ -15,6 +15,7 @@
"""Tests for nova websocketproxy."""
import copy
+import io
import socket
import mock
@@ -635,16 +636,6 @@ class NovaProxyRequestHandlerTestCase(test.NoDBTestCase):
b''
]
- # Collect the response data to verify at the end. The
- # SimpleHTTPRequestHandler writes the response data by calling the
- # request socket sendall() method.
- self.data = b''
-
- def fake_sendall(data):
- self.data += data
-
- mock_req.sendall.side_effect = fake_sendall
-
client_addr = ('8.8.8.8', 54321)
mock_server = mock.MagicMock()
# This specifies that the server will be able to handle requests other
@@ -652,13 +643,21 @@ class NovaProxyRequestHandlerTestCase(test.NoDBTestCase):
mock_server.only_upgrade = False
# Constructing a handler will process the mock_req request passed in.
- websocketproxy.NovaProxyRequestHandler(
+ handler = websocketproxy.NovaProxyRequestHandler(
mock_req, client_addr, mock_server)
+ # Collect the response data to verify at the end. The
+ # SimpleHTTPRequestHandler writes the response data to a 'wfile'
+ # attribute.
+ output = io.BytesIO()
+ handler.wfile = output
+ # Process the mock_req again to do the capture.
+ handler.do_GET()
+ output.seek(0)
+ result = output.readlines()
+
# Verify no redirect happens and instead a 400 Bad Request is returned.
- self.data = self.data.decode()
- self.assertIn('Error code: 400', self.data)
- self.assertIn('Message: URI must not start with //', self.data)
+ self.assertIn('400 URI must not start with //', result[0].decode())
@mock.patch('websockify.websocketproxy.select_ssl_version')
def test_ssl_min_version_is_not_set(self, mock_select_ssl):
diff --git a/nova/tests/unit/storage/test_rbd.py b/nova/tests/unit/storage/test_rbd.py
index 65796ebc1f..396f22c643 100644
--- a/nova/tests/unit/storage/test_rbd.py
+++ b/nova/tests/unit/storage/test_rbd.py
@@ -119,13 +119,15 @@ class RbdTestCase(test.NoDBTestCase):
rados_patcher = mock.patch.object(rbd_utils, 'rados')
self.mock_rados = rados_patcher.start()
self.addCleanup(rados_patcher.stop)
- self.mock_rados.Rados = mock.Mock
- self.mock_rados.Rados.ioctx = mock.Mock()
- self.mock_rados.Rados.connect = mock.Mock()
- self.mock_rados.Rados.shutdown = mock.Mock()
- self.mock_rados.Rados.open_ioctx = mock.Mock()
- self.mock_rados.Rados.open_ioctx.return_value = \
- self.mock_rados.Rados.ioctx
+ self.mock_rados.Rados = mock.Mock()
+ self.rados_inst = mock.Mock()
+ self.mock_rados.Rados.return_value = self.rados_inst
+ self.rados_inst.ioctx = mock.Mock()
+ self.rados_inst.connect = mock.Mock()
+ self.rados_inst.shutdown = mock.Mock()
+ self.rados_inst.open_ioctx = mock.Mock()
+ self.rados_inst.open_ioctx.return_value = \
+ self.rados_inst.ioctx
self.mock_rados.Error = Exception
rbd_patcher = mock.patch.object(rbd_utils, 'rbd')
@@ -339,33 +341,31 @@ class RbdTestCase(test.NoDBTestCase):
def test_connect_to_rados_default(self):
ret = self.driver._connect_to_rados()
- self.mock_rados.Rados.connect.assert_called_once_with(
+ self.rados_inst.connect.assert_called_once_with(
timeout=self.rbd_connect_timeout)
- self.assertTrue(self.mock_rados.Rados.open_ioctx.called)
- self.assertIsInstance(ret[0], self.mock_rados.Rados)
- self.assertEqual(self.mock_rados.Rados.ioctx, ret[1])
- self.mock_rados.Rados.open_ioctx.assert_called_with(self.rbd_pool)
+ self.assertTrue(self.rados_inst.open_ioctx.called)
+ self.assertEqual(self.rados_inst.ioctx, ret[1])
+ self.rados_inst.open_ioctx.assert_called_with(self.rbd_pool)
def test_connect_to_rados_different_pool(self):
ret = self.driver._connect_to_rados('alt_pool')
- self.mock_rados.Rados.connect.assert_called_once_with(
+ self.rados_inst.connect.assert_called_once_with(
timeout=self.rbd_connect_timeout)
- self.assertTrue(self.mock_rados.Rados.open_ioctx.called)
- self.assertIsInstance(ret[0], self.mock_rados.Rados)
- self.assertEqual(self.mock_rados.Rados.ioctx, ret[1])
- self.mock_rados.Rados.open_ioctx.assert_called_with('alt_pool')
+ self.assertTrue(self.rados_inst.open_ioctx.called)
+ self.assertEqual(self.rados_inst.ioctx, ret[1])
+ self.rados_inst.open_ioctx.assert_called_with('alt_pool')
def test_connect_to_rados_error(self):
- self.mock_rados.Rados.open_ioctx.side_effect = self.mock_rados.Error
+ self.rados_inst.open_ioctx.side_effect = self.mock_rados.Error
self.assertRaises(self.mock_rados.Error,
self.driver._connect_to_rados)
- self.mock_rados.Rados.open_ioctx.assert_called_once_with(
+ self.rados_inst.open_ioctx.assert_called_once_with(
self.rbd_pool)
- self.mock_rados.Rados.shutdown.assert_called_once_with()
+ self.rados_inst.shutdown.assert_called_once_with()
def test_connect_to_rados_unicode_arg(self):
self.driver._connect_to_rados(u'unicode_pool')
- self.mock_rados.Rados.open_ioctx.assert_called_with(
+ self.rados_inst.open_ioctx.assert_called_with(
test.MatchType(str))
def test_ceph_args_none(self):
diff --git a/nova/tests/unit/virt/libvirt/test_vif.py b/nova/tests/unit/virt/libvirt/test_vif.py
index b77d704bab..24df5d5aa7 100644
--- a/nova/tests/unit/virt/libvirt/test_vif.py
+++ b/nova/tests/unit/virt/libvirt/test_vif.py
@@ -379,6 +379,10 @@ class LibvirtVifTestCase(test.NoDBTestCase):
uuid='f0000000-0000-0000-0000-000000000001',
project_id=723)
+ flavor_1vcpu = objects.Flavor(vcpus=1, memory=512, root_gb=1)
+
+ flavor_2vcpu = objects.Flavor(vcpus=2, memory=512, root_gb=1)
+
bandwidth = {
'quota:vif_inbound_peak': '200',
'quota:vif_outbound_peak': '20',
@@ -1063,30 +1067,50 @@ 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_kvm_virtio(self, mock_create_tap_dev, mock_set_mtu,
- mock_device_exists):
+ def test_plug_tap_kvm_virtio(
+ 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',
+ flavor=self.flavor_2vcpu,
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.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',
+ flavor=self.flavor_2vcpu,
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_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_1vcpu(
+ self, mock_create_tap_dev, mock_set_mtu, mock_device_exists):
+
+ d1 = vif.LibvirtGenericVIFDriver()
+ mq_ins = objects.Instance(
+ id=1, uuid='f0000000-0000-0000-0000-000000000001',
+ image_ref=uuids.image_ref, flavor=self.flavor_1vcpu,
+ project_id=723, system_metadata={
+ 'image_hw_vif_multiqueue_enabled': 'True',
+ }
+ )
+ d1.plug(mq_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')
@@ -1101,14 +1125,14 @@ class LibvirtVifTestCase(test.NoDBTestCase):
d1 = vif.LibvirtGenericVIFDriver()
ins = objects.Instance(
id=1, uuid='f0000000-0000-0000-0000-000000000001',
+ flavor=self.flavor_2vcpu,
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_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')
@@ -1119,15 +1143,15 @@ class LibvirtVifTestCase(test.NoDBTestCase):
d1 = vif.LibvirtGenericVIFDriver()
ins = objects.Instance(
id=1, uuid='f0000000-0000-0000-0000-000000000001',
+ flavor=self.flavor_2vcpu,
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)
+ 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 5c87223baf..67e0771ad9 100644
--- a/nova/virt/libvirt/vif.py
+++ b/nova/virt/libvirt/vif.py
@@ -666,7 +666,8 @@ class LibvirtGenericVIFDriver(object):
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
+ multiqueue = (instance.get_flavor().vcpus > 1 and
+ 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')
diff --git a/releasenotes/notes/bug-1939604-547c729b7741831b.yaml b/releasenotes/notes/bug-1939604-547c729b7741831b.yaml
new file mode 100644
index 0000000000..e14327c285
--- /dev/null
+++ b/releasenotes/notes/bug-1939604-547c729b7741831b.yaml
@@ -0,0 +1,5 @@
+---
+fixes:
+ - |
+ Addressed an issue that prevented instances with 1 vcpu using multiqueue
+ feature from being created successfully when their vif_type is TAP.