diff options
-rw-r--r-- | nova/tests/unit/api/openstack/compute/test_services.py | 19 | ||||
-rw-r--r-- | nova/tests/unit/console/test_websocketproxy.py | 27 | ||||
-rw-r--r-- | nova/tests/unit/storage/test_rbd.py | 42 | ||||
-rw-r--r-- | nova/tests/unit/virt/libvirt/test_vif.py | 48 | ||||
-rw-r--r-- | nova/virt/libvirt/vif.py | 3 | ||||
-rw-r--r-- | releasenotes/notes/bug-1939604-547c729b7741831b.yaml | 5 |
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. |