summaryrefslogtreecommitdiff
path: root/nova/tests/unit/api/openstack
diff options
context:
space:
mode:
Diffstat (limited to 'nova/tests/unit/api/openstack')
-rw-r--r--nova/tests/unit/api/openstack/compute/admin_only_action_common.py3
-rw-r--r--nova/tests/unit/api/openstack/compute/test_admin_password.py4
-rw-r--r--nova/tests/unit/api/openstack/compute/test_aggregates.py3
-rw-r--r--nova/tests/unit/api/openstack/compute/test_api.py2
-rw-r--r--nova/tests/unit/api/openstack/compute/test_attach_interfaces.py3
-rw-r--r--nova/tests/unit/api/openstack/compute/test_availability_zone.py2
-rw-r--r--nova/tests/unit/api/openstack/compute/test_baremetal_nodes.py5
-rw-r--r--nova/tests/unit/api/openstack/compute/test_console_auth_tokens.py2
-rw-r--r--nova/tests/unit/api/openstack/compute/test_console_output.py2
-rw-r--r--nova/tests/unit/api/openstack/compute/test_create_backup.py7
-rw-r--r--nova/tests/unit/api/openstack/compute/test_deferred_delete.py3
-rw-r--r--nova/tests/unit/api/openstack/compute/test_disk_config.py2
-rw-r--r--nova/tests/unit/api/openstack/compute/test_evacuate.py32
-rw-r--r--nova/tests/unit/api/openstack/compute/test_flavor_access.py27
-rw-r--r--nova/tests/unit/api/openstack/compute/test_flavor_manage.py2
-rw-r--r--nova/tests/unit/api/openstack/compute/test_flavors.py2
-rw-r--r--nova/tests/unit/api/openstack/compute/test_flavors_extra_specs.py3
-rw-r--r--nova/tests/unit/api/openstack/compute/test_floating_ip_pools.py2
-rw-r--r--nova/tests/unit/api/openstack/compute/test_floating_ips.py3
-rw-r--r--nova/tests/unit/api/openstack/compute/test_hosts.py3
-rw-r--r--nova/tests/unit/api/openstack/compute/test_hypervisors.py396
-rw-r--r--nova/tests/unit/api/openstack/compute/test_image_metadata.py2
-rw-r--r--nova/tests/unit/api/openstack/compute/test_images.py2
-rw-r--r--nova/tests/unit/api/openstack/compute/test_instance_actions.py2
-rw-r--r--nova/tests/unit/api/openstack/compute/test_keypairs.py172
-rw-r--r--nova/tests/unit/api/openstack/compute/test_limits.py327
-rw-r--r--nova/tests/unit/api/openstack/compute/test_lock_server.py4
-rw-r--r--nova/tests/unit/api/openstack/compute/test_microversions.py3
-rw-r--r--nova/tests/unit/api/openstack/compute/test_migrate_server.py6
-rw-r--r--nova/tests/unit/api/openstack/compute/test_migrations.py2
-rw-r--r--nova/tests/unit/api/openstack/compute/test_multinic.py3
-rw-r--r--nova/tests/unit/api/openstack/compute/test_networks.py2
-rw-r--r--nova/tests/unit/api/openstack/compute/test_quota_classes.py224
-rw-r--r--nova/tests/unit/api/openstack/compute/test_quotas.py480
-rw-r--r--nova/tests/unit/api/openstack/compute/test_remote_consoles.py17
-rw-r--r--nova/tests/unit/api/openstack/compute/test_rescue.py2
-rw-r--r--nova/tests/unit/api/openstack/compute/test_security_groups.py3
-rw-r--r--nova/tests/unit/api/openstack/compute/test_server_actions.py41
-rw-r--r--nova/tests/unit/api/openstack/compute/test_server_diagnostics.py3
-rw-r--r--nova/tests/unit/api/openstack/compute/test_server_external_events.py5
-rw-r--r--nova/tests/unit/api/openstack/compute/test_server_group_quotas.py108
-rw-r--r--nova/tests/unit/api/openstack/compute/test_server_groups.py100
-rw-r--r--nova/tests/unit/api/openstack/compute/test_server_metadata.py3
-rw-r--r--nova/tests/unit/api/openstack/compute/test_server_migrations.py2
-rw-r--r--nova/tests/unit/api/openstack/compute/test_server_password.py2
-rw-r--r--nova/tests/unit/api/openstack/compute/test_server_reset_state.py3
-rw-r--r--nova/tests/unit/api/openstack/compute/test_server_start_stop.py3
-rw-r--r--nova/tests/unit/api/openstack/compute/test_server_tags.py3
-rw-r--r--nova/tests/unit/api/openstack/compute/test_server_topology.py3
-rw-r--r--nova/tests/unit/api/openstack/compute/test_servers.py41
-rw-r--r--nova/tests/unit/api/openstack/compute/test_services.py2
-rw-r--r--nova/tests/unit/api/openstack/compute/test_shelve.py258
-rw-r--r--nova/tests/unit/api/openstack/compute/test_simple_tenant_usage.py2
-rw-r--r--nova/tests/unit/api/openstack/compute/test_snapshots.py3
-rw-r--r--nova/tests/unit/api/openstack/compute/test_suspend_server.py3
-rw-r--r--nova/tests/unit/api/openstack/compute/test_tenant_networks.py2
-rw-r--r--nova/tests/unit/api/openstack/compute/test_volumes.py12
-rw-r--r--nova/tests/unit/api/openstack/fakes.py14
-rw-r--r--nova/tests/unit/api/openstack/test_common.py3
-rw-r--r--nova/tests/unit/api/openstack/test_faults.py3
-rw-r--r--nova/tests/unit/api/openstack/test_requestlog.py2
-rw-r--r--nova/tests/unit/api/openstack/test_wsgi.py3
-rw-r--r--nova/tests/unit/api/openstack/test_wsgi_app.py17
63 files changed, 1872 insertions, 528 deletions
diff --git a/nova/tests/unit/api/openstack/compute/admin_only_action_common.py b/nova/tests/unit/api/openstack/compute/admin_only_action_common.py
index 37fd1012b7..f332d9f32f 100644
--- a/nova/tests/unit/api/openstack/compute/admin_only_action_common.py
+++ b/nova/tests/unit/api/openstack/compute/admin_only_action_common.py
@@ -12,8 +12,9 @@
# License for the specific language governing permissions and limitations
# under the License.
+from unittest import mock
+
import fixtures
-import mock
from oslo_utils import timeutils
from oslo_utils import uuidutils
import webob
diff --git a/nova/tests/unit/api/openstack/compute/test_admin_password.py b/nova/tests/unit/api/openstack/compute/test_admin_password.py
index 90a4a2983b..67e4c743d5 100644
--- a/nova/tests/unit/api/openstack/compute/test_admin_password.py
+++ b/nova/tests/unit/api/openstack/compute/test_admin_password.py
@@ -13,7 +13,9 @@
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
-import mock
+
+from unittest import mock
+
import webob
from nova.api.openstack.compute import admin_password as admin_password_v21
diff --git a/nova/tests/unit/api/openstack/compute/test_aggregates.py b/nova/tests/unit/api/openstack/compute/test_aggregates.py
index fb096861eb..21d644f0be 100644
--- a/nova/tests/unit/api/openstack/compute/test_aggregates.py
+++ b/nova/tests/unit/api/openstack/compute/test_aggregates.py
@@ -15,7 +15,8 @@
"""Tests for the aggregates admin api."""
-import mock
+from unittest import mock
+
from oslo_utils.fixture import uuidsentinel
from webob import exc
diff --git a/nova/tests/unit/api/openstack/compute/test_api.py b/nova/tests/unit/api/openstack/compute/test_api.py
index ca54be9a74..d1bb6babb7 100644
--- a/nova/tests/unit/api/openstack/compute/test_api.py
+++ b/nova/tests/unit/api/openstack/compute/test_api.py
@@ -143,7 +143,7 @@ class APITest(test.NoDBTestCase):
self.assertEqual(resp.headers[key], str(value))
def test_quota_error_mapping(self):
- self._do_test_exception_mapping(exception.QuotaError, 'too many used')
+ self._do_test_exception_mapping(exception.OverQuota, 'too many used')
def test_non_nova_notfound_exception_mapping(self):
class ExceptionWithCode(Exception):
diff --git a/nova/tests/unit/api/openstack/compute/test_attach_interfaces.py b/nova/tests/unit/api/openstack/compute/test_attach_interfaces.py
index 526cb6011d..e4719ea052 100644
--- a/nova/tests/unit/api/openstack/compute/test_attach_interfaces.py
+++ b/nova/tests/unit/api/openstack/compute/test_attach_interfaces.py
@@ -13,7 +13,8 @@
# License for the specific language governing permissions and limitations
# under the License.
-import mock
+from unittest import mock
+
from webob import exc
from nova.api.openstack import common
diff --git a/nova/tests/unit/api/openstack/compute/test_availability_zone.py b/nova/tests/unit/api/openstack/compute/test_availability_zone.py
index f355eb436a..a408e0d1aa 100644
--- a/nova/tests/unit/api/openstack/compute/test_availability_zone.py
+++ b/nova/tests/unit/api/openstack/compute/test_availability_zone.py
@@ -13,9 +13,9 @@
# under the License.
import datetime
+from unittest import mock
import iso8601
-import mock
from oslo_serialization import jsonutils
from oslo_utils.fixture import uuidsentinel
diff --git a/nova/tests/unit/api/openstack/compute/test_baremetal_nodes.py b/nova/tests/unit/api/openstack/compute/test_baremetal_nodes.py
index 55a8b03216..c8ad907b10 100644
--- a/nova/tests/unit/api/openstack/compute/test_baremetal_nodes.py
+++ b/nova/tests/unit/api/openstack/compute/test_baremetal_nodes.py
@@ -13,13 +13,12 @@
# License for the specific language governing permissions and limitations
# under the License.
+from unittest import mock
from ironicclient import exc as ironic_exc
-import mock
from webob import exc
-from nova.api.openstack.compute import baremetal_nodes \
- as b_nodes_v21
+from nova.api.openstack.compute import baremetal_nodes as b_nodes_v21
from nova import context
from nova import exception
from nova import test
diff --git a/nova/tests/unit/api/openstack/compute/test_console_auth_tokens.py b/nova/tests/unit/api/openstack/compute/test_console_auth_tokens.py
index 429096d51d..a1f3d1e63d 100644
--- a/nova/tests/unit/api/openstack/compute/test_console_auth_tokens.py
+++ b/nova/tests/unit/api/openstack/compute/test_console_auth_tokens.py
@@ -14,8 +14,8 @@
# under the License.
import copy
+from unittest import mock
-import mock
import webob
from nova.api.openstack import api_version_request
diff --git a/nova/tests/unit/api/openstack/compute/test_console_output.py b/nova/tests/unit/api/openstack/compute/test_console_output.py
index 1a76a445fc..a9dc830255 100644
--- a/nova/tests/unit/api/openstack/compute/test_console_output.py
+++ b/nova/tests/unit/api/openstack/compute/test_console_output.py
@@ -14,8 +14,8 @@
# under the License.
import string
+from unittest import mock
-import mock
import webob
from nova.api.openstack.compute import console_output \
diff --git a/nova/tests/unit/api/openstack/compute/test_create_backup.py b/nova/tests/unit/api/openstack/compute/test_create_backup.py
index f7280a5a37..9728002e88 100644
--- a/nova/tests/unit/api/openstack/compute/test_create_backup.py
+++ b/nova/tests/unit/api/openstack/compute/test_create_backup.py
@@ -13,7 +13,8 @@
# License for the specific language governing permissions and limitations
# under the License.
-import mock
+from unittest import mock
+
from oslo_utils import timeutils
import webob
@@ -40,10 +41,6 @@ class CreateBackupTestsV21(admin_only_action_common.CommonMixin,
self.controller = getattr(self.create_backup, self.controller_name)()
self.compute_api = self.controller.compute_api
- patch_get = mock.patch.object(self.compute_api, 'get')
- self.mock_get = patch_get.start()
- self.addCleanup(patch_get.stop)
-
@mock.patch.object(common, 'check_img_metadata_properties_quota')
@mock.patch.object(api.API, 'backup')
def test_create_backup_with_metadata(self, mock_backup, mock_check_image):
diff --git a/nova/tests/unit/api/openstack/compute/test_deferred_delete.py b/nova/tests/unit/api/openstack/compute/test_deferred_delete.py
index db6f774c51..8a1c8efd57 100644
--- a/nova/tests/unit/api/openstack/compute/test_deferred_delete.py
+++ b/nova/tests/unit/api/openstack/compute/test_deferred_delete.py
@@ -13,7 +13,8 @@
# License for the specific language governing permissions and limitations
# under the License.
-import mock
+from unittest import mock
+
import webob
from nova.api.openstack.compute import deferred_delete as dd_v21
diff --git a/nova/tests/unit/api/openstack/compute/test_disk_config.py b/nova/tests/unit/api/openstack/compute/test_disk_config.py
index bf3be1d0a3..c5ee59722a 100644
--- a/nova/tests/unit/api/openstack/compute/test_disk_config.py
+++ b/nova/tests/unit/api/openstack/compute/test_disk_config.py
@@ -14,8 +14,8 @@
# under the License.
import datetime
+from unittest import mock
-import mock
from oslo_serialization import jsonutils
from nova.api.openstack import compute
diff --git a/nova/tests/unit/api/openstack/compute/test_evacuate.py b/nova/tests/unit/api/openstack/compute/test_evacuate.py
index 6620d7a180..bd88bb8d6e 100644
--- a/nova/tests/unit/api/openstack/compute/test_evacuate.py
+++ b/nova/tests/unit/api/openstack/compute/test_evacuate.py
@@ -12,8 +12,9 @@
# License for the specific language governing permissions and limitations
# under the License.
+from unittest import mock
+
import fixtures
-import mock
from oslo_utils.fixture import uuidsentinel as uuids
import testtools
import webob
@@ -415,3 +416,32 @@ class EvacuateTestV268(EvacuateTestV229):
def test_forced_evacuate_with_no_host_provided(self):
# not applicable for v2.68, which removed the 'force' parameter
pass
+
+
+class EvacuateTestV295(EvacuateTestV268):
+ def setUp(self):
+ super(EvacuateTestV268, self).setUp()
+ self.admin_req = fakes.HTTPRequest.blank('', use_admin_context=True,
+ version='2.95')
+ self.req = fakes.HTTPRequest.blank('', version='2.95')
+ self.mock_get_min_ver = self.useFixture(fixtures.MockPatch(
+ 'nova.objects.service.get_minimum_version_all_cells',
+ return_value=62)).mock
+
+ def test_evacuate_version_error(self):
+ self.mock_get_min_ver.return_value = 61
+ self.assertRaises(webob.exc.HTTPBadRequest,
+ self._get_evacuate_response,
+ {'host': 'my-host', 'adminPass': 'foo'})
+
+ def test_evacuate_unsupported_rpc(self):
+ def fake_evacuate(*args, **kwargs):
+ raise exception.UnsupportedRPCVersion(
+ api="fakeapi",
+ required="x.xx")
+
+ self.stub_out('nova.compute.api.API.evacuate', fake_evacuate)
+ self._check_evacuate_failure(webob.exc.HTTPConflict,
+ {'host': 'my-host',
+ 'onSharedStorage': 'False',
+ 'adminPass': 'MyNewPass'})
diff --git a/nova/tests/unit/api/openstack/compute/test_flavor_access.py b/nova/tests/unit/api/openstack/compute/test_flavor_access.py
index 8c25a2efc2..ea9ca2f632 100644
--- a/nova/tests/unit/api/openstack/compute/test_flavor_access.py
+++ b/nova/tests/unit/api/openstack/compute/test_flavor_access.py
@@ -14,8 +14,8 @@
# under the License.
import datetime
+from unittest import mock
-import mock
from webob import exc
from nova.api.openstack import api_version_request as api_version
@@ -353,14 +353,37 @@ class FlavorAccessTestV21(test.NoDBTestCase):
mock_verify.assert_called_once_with(
req.environ['nova.context'], 'proj2')
+ @mock.patch('nova.objects.Flavor.remove_access')
@mock.patch('nova.api.openstack.identity.verify_project_id',
side_effect=exc.HTTPBadRequest(
explanation="Project ID proj2 is not a valid project."))
- def test_remove_tenant_access_with_invalid_tenant(self, mock_verify):
+ def test_remove_tenant_access_with_invalid_tenant(self,
+ mock_verify,
+ mock_remove_access):
"""Tests the case that the tenant does not exist in Keystone."""
req = fakes.HTTPRequest.blank(self._prefix + '/flavors/2/action',
use_admin_context=True)
body = {'removeTenantAccess': {'tenant': 'proj2'}}
+
+ self.flavor_action_controller._remove_tenant_access(
+ req, '2', body=body)
+ mock_verify.assert_called_once_with(
+ req.environ['nova.context'], 'proj2')
+ mock_remove_access.assert_called_once_with('proj2')
+
+ @mock.patch('nova.api.openstack.identity.verify_project_id',
+ side_effect=exc.HTTPBadRequest(
+ explanation="Nova was unable to find Keystone "
+ "service endpoint."))
+ def test_remove_tenant_access_missing_keystone_endpoint(self,
+ mock_verify):
+ """Tests the case that Keystone identity service endpoint
+ version 3.0 was not found.
+ """
+ req = fakes.HTTPRequest.blank(self._prefix + '/flavors/2/action',
+ use_admin_context=True)
+ body = {'removeTenantAccess': {'tenant': 'proj2'}}
+
self.assertRaises(exc.HTTPBadRequest,
self.flavor_action_controller._remove_tenant_access,
req, '2', body=body)
diff --git a/nova/tests/unit/api/openstack/compute/test_flavor_manage.py b/nova/tests/unit/api/openstack/compute/test_flavor_manage.py
index f8412c772c..948f255f34 100644
--- a/nova/tests/unit/api/openstack/compute/test_flavor_manage.py
+++ b/nova/tests/unit/api/openstack/compute/test_flavor_manage.py
@@ -14,8 +14,8 @@
# under the License.
import copy
+from unittest import mock
-import mock
from oslo_serialization import jsonutils
import webob
diff --git a/nova/tests/unit/api/openstack/compute/test_flavors.py b/nova/tests/unit/api/openstack/compute/test_flavors.py
index 4390b32012..c7fbf5c468 100644
--- a/nova/tests/unit/api/openstack/compute/test_flavors.py
+++ b/nova/tests/unit/api/openstack/compute/test_flavors.py
@@ -13,9 +13,9 @@
# License for the specific language governing permissions and limitations
# under the License.
+from unittest import mock
from urllib import parse as urlparse
-import mock
import webob
from nova.api.openstack import common
diff --git a/nova/tests/unit/api/openstack/compute/test_flavors_extra_specs.py b/nova/tests/unit/api/openstack/compute/test_flavors_extra_specs.py
index e68bf7e306..8355ce59b5 100644
--- a/nova/tests/unit/api/openstack/compute/test_flavors_extra_specs.py
+++ b/nova/tests/unit/api/openstack/compute/test_flavors_extra_specs.py
@@ -13,7 +13,8 @@
# License for the specific language governing permissions and limitations
# under the License.
-import mock
+from unittest import mock
+
import testtools
import webob
diff --git a/nova/tests/unit/api/openstack/compute/test_floating_ip_pools.py b/nova/tests/unit/api/openstack/compute/test_floating_ip_pools.py
index e25302ee9a..71ca209672 100644
--- a/nova/tests/unit/api/openstack/compute/test_floating_ip_pools.py
+++ b/nova/tests/unit/api/openstack/compute/test_floating_ip_pools.py
@@ -13,7 +13,7 @@
# License for the specific language governing permissions and limitations
# under the License.
-import mock
+from unittest import mock
from nova.api.openstack.compute import floating_ip_pools \
as fipp_v21
diff --git a/nova/tests/unit/api/openstack/compute/test_floating_ips.py b/nova/tests/unit/api/openstack/compute/test_floating_ips.py
index 2cb89dfe76..7093c5a80d 100644
--- a/nova/tests/unit/api/openstack/compute/test_floating_ips.py
+++ b/nova/tests/unit/api/openstack/compute/test_floating_ips.py
@@ -14,7 +14,8 @@
# License for the specific language governing permissions and limitations
# under the License.
-import mock
+from unittest import mock
+
from oslo_utils.fixture import uuidsentinel as uuids
import webob
diff --git a/nova/tests/unit/api/openstack/compute/test_hosts.py b/nova/tests/unit/api/openstack/compute/test_hosts.py
index 7adc698093..f1cdde2917 100644
--- a/nova/tests/unit/api/openstack/compute/test_hosts.py
+++ b/nova/tests/unit/api/openstack/compute/test_hosts.py
@@ -13,7 +13,8 @@
# License for the specific language governing permissions and limitations
# under the License.
-import mock
+from unittest import mock
+
from oslo_utils.fixture import uuidsentinel
import testtools
import webob.exc
diff --git a/nova/tests/unit/api/openstack/compute/test_hypervisors.py b/nova/tests/unit/api/openstack/compute/test_hypervisors.py
index facc5389be..a908988811 100644
--- a/nova/tests/unit/api/openstack/compute/test_hypervisors.py
+++ b/nova/tests/unit/api/openstack/compute/test_hypervisors.py
@@ -14,8 +14,8 @@
# under the License.
import copy
+from unittest import mock
-import mock
import netaddr
from oslo_serialization import jsonutils
from oslo_utils.fixture import uuidsentinel as uuids
@@ -368,25 +368,23 @@ class HypervisorsTestV21(test.NoDBTestCase):
return TEST_SERVICES[0]
raise exception.ComputeHostNotFound(host=host)
- @mock.patch.object(self.controller.host_api, 'compute_node_get_all',
- return_value=compute_nodes)
- @mock.patch.object(self.controller.host_api,
- 'service_get_by_compute_host',
- fake_service_get_by_compute_host)
- def _test(self, compute_node_get_all):
- req = self._get_request(True)
- result = self.controller.index(req)
- self.assertEqual(1, len(result['hypervisors']))
- expected = {
- 'id': compute_nodes[0].uuid if self.expect_uuid_for_id
- else compute_nodes[0].id,
- 'hypervisor_hostname': compute_nodes[0].hypervisor_hostname,
- 'state': 'up',
- 'status': 'enabled',
- }
- self.assertDictEqual(expected, result['hypervisors'][0])
+ m_get = self.controller.host_api.compute_node_get_all
+ m_get.side_effect = None
+ m_get.return_value = compute_nodes
+ self.controller.host_api.service_get_by_compute_host.side_effect = (
+ fake_service_get_by_compute_host)
- _test(self)
+ req = self._get_request(True)
+ result = self.controller.index(req)
+ self.assertEqual(1, len(result['hypervisors']))
+ expected = {
+ 'id': compute_nodes[0].uuid if self.expect_uuid_for_id
+ else compute_nodes[0].id,
+ 'hypervisor_hostname': compute_nodes[0].hypervisor_hostname,
+ 'state': 'up',
+ 'status': 'enabled',
+ }
+ self.assertDictEqual(expected, result['hypervisors'][0])
def test_index_compute_host_not_mapped(self):
"""Tests that we don't fail index if a host is not mapped."""
@@ -402,25 +400,22 @@ class HypervisorsTestV21(test.NoDBTestCase):
return TEST_SERVICES[0]
raise exception.HostMappingNotFound(name=host)
- @mock.patch.object(self.controller.host_api, 'compute_node_get_all',
- return_value=compute_nodes)
- @mock.patch.object(self.controller.host_api,
- 'service_get_by_compute_host',
- fake_service_get_by_compute_host)
- def _test(self, compute_node_get_all):
- req = self._get_request(True)
- result = self.controller.index(req)
- self.assertEqual(1, len(result['hypervisors']))
- expected = {
- 'id': compute_nodes[0].uuid if self.expect_uuid_for_id
- else compute_nodes[0].id,
- 'hypervisor_hostname': compute_nodes[0].hypervisor_hostname,
- 'state': 'up',
- 'status': 'enabled',
- }
- self.assertDictEqual(expected, result['hypervisors'][0])
+ self.controller.host_api.compute_node_get_all.return_value = (
+ compute_nodes)
+ self.controller.host_api.service_get_by_compute_host = (
+ fake_service_get_by_compute_host)
- _test(self)
+ req = self._get_request(True)
+ result = self.controller.index(req)
+ self.assertEqual(1, len(result['hypervisors']))
+ expected = {
+ 'id': compute_nodes[0].uuid if self.expect_uuid_for_id
+ else compute_nodes[0].id,
+ 'hypervisor_hostname': compute_nodes[0].hypervisor_hostname,
+ 'state': 'up',
+ 'status': 'enabled',
+ }
+ self.assertDictEqual(expected, result['hypervisors'][0])
def test_detail(self):
req = self._get_request(True)
@@ -444,32 +439,30 @@ class HypervisorsTestV21(test.NoDBTestCase):
return TEST_SERVICES[0]
raise exception.ComputeHostNotFound(host=host)
- @mock.patch.object(self.controller.host_api, 'compute_node_get_all',
- return_value=compute_nodes)
- @mock.patch.object(self.controller.host_api,
- 'service_get_by_compute_host',
- fake_service_get_by_compute_host)
- def _test(self, compute_node_get_all):
- req = self._get_request(True)
- result = self.controller.detail(req)
- self.assertEqual(1, len(result['hypervisors']))
- expected = {
- 'id': compute_nodes[0].id,
- 'hypervisor_hostname': compute_nodes[0].hypervisor_hostname,
- 'state': 'up',
- 'status': 'enabled',
- }
- # we don't care about all of the details, just make sure we get
- # the subset we care about and there are more keys than what index
- # would return
- hypervisor = result['hypervisors'][0]
- self.assertTrue(
- set(expected.keys()).issubset(set(hypervisor.keys())))
- self.assertGreater(len(hypervisor.keys()), len(expected.keys()))
- self.assertEqual(compute_nodes[0].hypervisor_hostname,
- hypervisor['hypervisor_hostname'])
-
- _test(self)
+ m_get = self.controller.host_api.compute_node_get_all
+ m_get.side_effect = None
+ m_get.return_value = compute_nodes
+ self.controller.host_api.service_get_by_compute_host.side_effect = (
+ fake_service_get_by_compute_host)
+
+ req = self._get_request(True)
+ result = self.controller.detail(req)
+ self.assertEqual(1, len(result['hypervisors']))
+ expected = {
+ 'id': compute_nodes[0].id,
+ 'hypervisor_hostname': compute_nodes[0].hypervisor_hostname,
+ 'state': 'up',
+ 'status': 'enabled',
+ }
+ # we don't care about all of the details, just make sure we get
+ # the subset we care about and there are more keys than what index
+ # would return
+ hypervisor = result['hypervisors'][0]
+ self.assertTrue(
+ set(expected.keys()).issubset(set(hypervisor.keys())))
+ self.assertGreater(len(hypervisor.keys()), len(expected.keys()))
+ self.assertEqual(compute_nodes[0].hypervisor_hostname,
+ hypervisor['hypervisor_hostname'])
def test_detail_compute_host_not_mapped(self):
"""Tests that if a service is deleted but the compute node is not we
@@ -487,32 +480,28 @@ class HypervisorsTestV21(test.NoDBTestCase):
return TEST_SERVICES[0]
raise exception.HostMappingNotFound(name=host)
- @mock.patch.object(self.controller.host_api, 'compute_node_get_all',
- return_value=compute_nodes)
- @mock.patch.object(self.controller.host_api,
- 'service_get_by_compute_host',
- fake_service_get_by_compute_host)
- def _test(self, compute_node_get_all):
- req = self._get_request(True)
- result = self.controller.detail(req)
- self.assertEqual(1, len(result['hypervisors']))
- expected = {
- 'id': compute_nodes[0].id,
- 'hypervisor_hostname': compute_nodes[0].hypervisor_hostname,
- 'state': 'up',
- 'status': 'enabled',
- }
- # we don't care about all of the details, just make sure we get
- # the subset we care about and there are more keys than what index
- # would return
- hypervisor = result['hypervisors'][0]
- self.assertTrue(
- set(expected.keys()).issubset(set(hypervisor.keys())))
- self.assertGreater(len(hypervisor.keys()), len(expected.keys()))
- self.assertEqual(compute_nodes[0].hypervisor_hostname,
- hypervisor['hypervisor_hostname'])
-
- _test(self)
+ self.controller.host_api.service_get_by_compute_host.side_effect = (
+ fake_service_get_by_compute_host)
+ self.controller.host_api.compute_node_get_all.return_value = (
+ compute_nodes)
+ req = self._get_request(True)
+ result = self.controller.detail(req)
+ self.assertEqual(1, len(result['hypervisors']))
+ expected = {
+ 'id': compute_nodes[0].id,
+ 'hypervisor_hostname': compute_nodes[0].hypervisor_hostname,
+ 'state': 'up',
+ 'status': 'enabled',
+ }
+ # we don't care about all of the details, just make sure we get
+ # the subset we care about and there are more keys than what index
+ # would return
+ hypervisor = result['hypervisors'][0]
+ self.assertTrue(
+ set(expected.keys()).issubset(set(hypervisor.keys())))
+ self.assertGreater(len(hypervisor.keys()), len(expected.keys()))
+ self.assertEqual(compute_nodes[0].hypervisor_hostname,
+ hypervisor['hypervisor_hostname'])
def test_show(self):
req = self._get_request(True)
@@ -525,21 +514,16 @@ class HypervisorsTestV21(test.NoDBTestCase):
"""Tests that if a service is deleted but the compute node is not we
don't fail when listing hypervisors.
"""
-
- @mock.patch.object(self.controller.host_api, 'compute_node_get',
- return_value=self.TEST_HYPERS_OBJ[0])
- @mock.patch.object(self.controller.host_api,
- 'service_get_by_compute_host')
- def _test(self, mock_service, mock_compute_node_get):
- req = self._get_request(True)
- mock_service.side_effect = exception.HostMappingNotFound(
- name='foo')
- hyper_id = self._get_hyper_id()
- self.assertRaises(exc.HTTPNotFound, self.controller.show,
- req, hyper_id)
- self.assertTrue(mock_service.called)
- mock_compute_node_get.assert_called_once_with(mock.ANY, hyper_id)
- _test(self)
+ self.controller.host_api.service_get_by_compute_host.side_effect = (
+ exception.HostMappingNotFound(name='foo'))
+ req = self._get_request(True)
+ hyper_id = self._get_hyper_id()
+ self.assertRaises(
+ exc.HTTPNotFound, self.controller.show, req, hyper_id)
+ self.assertTrue(
+ self.controller.host_api.service_get_by_compute_host.called)
+ self.controller.host_api.compute_node_get.assert_called_once_with(
+ mock.ANY, hyper_id)
def test_show_noid(self):
req = self._get_request(True)
@@ -611,20 +595,15 @@ class HypervisorsTestV21(test.NoDBTestCase):
mock.ANY, self.TEST_HYPERS_OBJ[0].host)
def test_uptime_hypervisor_not_mapped_service_get(self):
- @mock.patch.object(self.controller.host_api, 'compute_node_get')
- @mock.patch.object(self.controller.host_api, 'get_host_uptime')
- @mock.patch.object(self.controller.host_api,
- 'service_get_by_compute_host',
- side_effect=exception.HostMappingNotFound(
- name='dummy'))
- def _test(mock_get, _, __):
- req = self._get_request(True)
- hyper_id = self._get_hyper_id()
- self.assertRaises(exc.HTTPNotFound,
- self.controller.uptime, req, hyper_id)
- self.assertTrue(mock_get.called)
+ self.controller.host_api.service_get_by_compute_host.side_effect = (
+ exception.HostMappingNotFound(name='dummy'))
- _test()
+ req = self._get_request(True)
+ hyper_id = self._get_hyper_id()
+ self.assertRaises(exc.HTTPNotFound,
+ self.controller.uptime, req, hyper_id)
+ self.assertTrue(
+ self.controller.host_api.service_get_by_compute_host.called)
def test_uptime_hypervisor_not_mapped(self):
with mock.patch.object(self.controller.host_api, 'get_host_uptime',
@@ -644,30 +623,26 @@ class HypervisorsTestV21(test.NoDBTestCase):
self.assertEqual(dict(hypervisors=self.INDEX_HYPER_DICTS), result)
def test_search_non_exist(self):
- with mock.patch.object(self.controller.host_api,
- 'compute_node_search_by_hypervisor',
- return_value=[]) as mock_node_search:
- req = self._get_request(True)
- self.assertRaises(exc.HTTPNotFound, self.controller.search,
- req, 'a')
- self.assertEqual(1, mock_node_search.call_count)
+ m_search = self.controller.host_api.compute_node_search_by_hypervisor
+ m_search.side_effect = None
+ m_search.return_value = []
+
+ req = self._get_request(True)
+ self.assertRaises(exc.HTTPNotFound, self.controller.search, req, 'a')
+ self.assertEqual(1, m_search.call_count)
def test_search_unmapped(self):
+ m_search = self.controller.host_api.compute_node_search_by_hypervisor
+ m_search.side_effect = None
+ m_search.return_value = [mock.MagicMock()]
- @mock.patch.object(self.controller.host_api,
- 'compute_node_search_by_hypervisor')
- @mock.patch.object(self.controller.host_api,
- 'service_get_by_compute_host')
- def _test(mock_service, mock_search):
- mock_search.return_value = [mock.MagicMock()]
- mock_service.side_effect = exception.HostMappingNotFound(
- name='foo')
- req = self._get_request(True)
- self.assertRaises(exc.HTTPNotFound, self.controller.search,
- req, 'a')
- self.assertTrue(mock_service.called)
+ self.controller.host_api.service_get_by_compute_host.side_effect = (
+ exception.HostMappingNotFound(name='foo'))
- _test()
+ req = self._get_request(True)
+ self.assertRaises(exc.HTTPNotFound, self.controller.search, req, 'a')
+ self.assertTrue(
+ self.controller.host_api.service_get_by_compute_host.called)
@mock.patch.object(objects.InstanceList, 'get_by_host',
side_effect=fake_instance_get_all_by_host)
@@ -702,15 +677,12 @@ class HypervisorsTestV21(test.NoDBTestCase):
def test_servers_compute_host_not_found(self):
req = self._get_request(True)
- with test.nested(
- mock.patch.object(
- self.controller.host_api, 'instance_get_all_by_host',
- side_effect=fake_instance_get_all_by_host,
- ),
- mock.patch.object(
- self.controller.host_api, 'service_get_by_compute_host',
- side_effect=exception.ComputeHostNotFound(host='foo'),
- ),
+ self.controller.host_api.service_get_by_compute_host.side_effect = (
+ exception.ComputeHostNotFound(host='foo'))
+ with mock.patch.object(
+ self.controller.host_api,
+ 'instance_get_all_by_host',
+ side_effect=fake_instance_get_all_by_host,
):
# The result should be empty since every attempt to fetch the
# service for a hypervisor "failed"
@@ -718,24 +690,25 @@ class HypervisorsTestV21(test.NoDBTestCase):
self.assertEqual({'hypervisors': []}, result)
def test_servers_non_id(self):
- with mock.patch.object(self.controller.host_api,
- 'compute_node_search_by_hypervisor',
- return_value=[]) as mock_node_search:
- req = self._get_request(True)
- self.assertRaises(exc.HTTPNotFound,
- self.controller.servers,
- req, '115')
- self.assertEqual(1, mock_node_search.call_count)
+ m_search = self.controller.host_api.compute_node_search_by_hypervisor
+ m_search.side_effect = None
+ m_search.return_value = []
+
+ req = self._get_request(True)
+ self.assertRaises(exc.HTTPNotFound,
+ self.controller.servers,
+ req, '115')
+ self.assertEqual(1, m_search.call_count)
def test_servers_with_non_integer_hypervisor_id(self):
- with mock.patch.object(self.controller.host_api,
- 'compute_node_search_by_hypervisor',
- return_value=[]) as mock_node_search:
+ m_search = self.controller.host_api.compute_node_search_by_hypervisor
+ m_search.side_effect = None
+ m_search.return_value = []
- req = self._get_request(True)
- self.assertRaises(exc.HTTPNotFound,
- self.controller.servers, req, 'abc')
- self.assertEqual(1, mock_node_search.call_count)
+ req = self._get_request(True)
+ self.assertRaises(
+ exc.HTTPNotFound, self.controller.servers, req, 'abc')
+ self.assertEqual(1, m_search.call_count)
def test_servers_with_no_servers(self):
with mock.patch.object(self.controller.host_api,
@@ -1089,15 +1062,13 @@ class HypervisorsTestV253(HypervisorsTestV252):
use_admin_context=True,
url='/os-hypervisors?with_servers=1')
- with test.nested(
- mock.patch.object(
- self.controller.host_api, 'instance_get_all_by_host',
- side_effect=fake_instance_get_all_by_host,
- ),
- mock.patch.object(
- self.controller.host_api, 'service_get_by_compute_host',
- side_effect=exception.ComputeHostNotFound(host='foo'),
- ),
+ self.controller.host_api.service_get_by_compute_host.side_effect = (
+ exception.ComputeHostNotFound(host='foo'))
+
+ with mock.patch.object(
+ self.controller.host_api,
+ "instance_get_all_by_host",
+ side_effect=fake_instance_get_all_by_host,
):
# The result should be empty since every attempt to fetch the
# service for a hypervisor "failed"
@@ -1157,11 +1128,13 @@ class HypervisorsTestV253(HypervisorsTestV252):
use_admin_context=True,
url='/os-hypervisors?with_servers=yes&'
'hypervisor_hostname_pattern=shenzhen')
- with mock.patch.object(self.controller.host_api,
- 'compute_node_search_by_hypervisor',
- return_value=objects.ComputeNodeList()) as s:
- self.assertRaises(exc.HTTPNotFound, self.controller.index, req)
- s.assert_called_once_with(req.environ['nova.context'], 'shenzhen')
+ m_search = self.controller.host_api.compute_node_search_by_hypervisor
+ m_search.side_effect = None
+ m_search.return_value = objects.ComputeNodeList()
+
+ self.assertRaises(exc.HTTPNotFound, self.controller.index, req)
+ m_search.assert_called_once_with(
+ req.environ['nova.context'], 'shenzhen')
def test_detail_with_hostname_pattern(self):
"""Test listing hypervisors with details and using the
@@ -1170,13 +1143,14 @@ class HypervisorsTestV253(HypervisorsTestV252):
req = self._get_request(
use_admin_context=True,
url='/os-hypervisors?hypervisor_hostname_pattern=shenzhen')
- with mock.patch.object(
- self.controller.host_api,
- 'compute_node_search_by_hypervisor',
- return_value=objects.ComputeNodeList(objects=[TEST_HYPERS_OBJ[0]])
- ) as s:
- result = self.controller.detail(req)
- s.assert_called_once_with(req.environ['nova.context'], 'shenzhen')
+ m_search = self.controller.host_api.compute_node_search_by_hypervisor
+ m_search.side_effect = None
+ m_search.return_value = objects.ComputeNodeList(
+ objects=[TEST_HYPERS_OBJ[0]])
+
+ result = self.controller.detail(req)
+ m_search.assert_called_once_with(
+ req.environ['nova.context'], 'shenzhen')
expected = {'hypervisors': [self.DETAIL_HYPERS_DICTS[0]]}
@@ -1483,15 +1457,11 @@ class HypervisorsTestV288(HypervisorsTestV275):
self.controller.uptime, req)
def test_uptime_old_version(self):
- with mock.patch.object(
- self.controller.host_api, 'get_host_uptime',
- return_value='fake uptime',
- ):
- req = self._get_request(use_admin_context=True, version='2.87')
- hyper_id = self._get_hyper_id()
+ req = self._get_request(use_admin_context=True, version='2.87')
+ hyper_id = self._get_hyper_id()
- # no exception == pass
- self.controller.uptime(req, hyper_id)
+ # no exception == pass
+ self.controller.uptime(req, hyper_id)
def test_uptime_noid(self):
# the separate 'uptime' API has been removed, so skip this test
@@ -1526,34 +1496,36 @@ class HypervisorsTestV288(HypervisorsTestV275):
pass
def test_show_with_uptime_notimplemented(self):
- with mock.patch.object(
- self.controller.host_api, 'get_host_uptime',
- side_effect=NotImplementedError,
- ) as mock_get_uptime:
- req = self._get_request(use_admin_context=True)
- hyper_id = self._get_hyper_id()
+ self.controller.host_api.get_host_uptime.side_effect = (
+ NotImplementedError())
- result = self.controller.show(req, hyper_id)
+ req = self._get_request(use_admin_context=True)
+ hyper_id = self._get_hyper_id()
- expected_dict = copy.deepcopy(self.DETAIL_HYPERS_DICTS[0])
- expected_dict.update({'uptime': None})
- self.assertEqual({'hypervisor': expected_dict}, result)
- self.assertEqual(1, mock_get_uptime.call_count)
+ result = self.controller.show(req, hyper_id)
+
+ expected_dict = copy.deepcopy(self.DETAIL_HYPERS_DICTS[0])
+ expected_dict.update({'uptime': None})
+ self.assertEqual({'hypervisor': expected_dict}, result)
+ self.assertEqual(
+ 1, self.controller.host_api.get_host_uptime.call_count)
def test_show_with_uptime_hypervisor_down(self):
- with mock.patch.object(
- self.controller.host_api, 'get_host_uptime',
- side_effect=exception.ComputeServiceUnavailable(host='dummy')
- ) as mock_get_uptime:
- req = self._get_request(use_admin_context=True)
- hyper_id = self._get_hyper_id()
+ self.controller.host_api.get_host_uptime.side_effect = (
+ exception.ComputeServiceUnavailable(host='dummy'))
- result = self.controller.show(req, hyper_id)
+ req = self._get_request(use_admin_context=True)
+ hyper_id = self._get_hyper_id()
- expected_dict = copy.deepcopy(self.DETAIL_HYPERS_DICTS[0])
- expected_dict.update({'uptime': None})
- self.assertEqual({'hypervisor': expected_dict}, result)
- self.assertEqual(1, mock_get_uptime.call_count)
+ result = self.controller.show(req, hyper_id)
+
+ expected_dict = copy.deepcopy(self.DETAIL_HYPERS_DICTS[0])
+ expected_dict.update({'uptime': None})
+ self.assertEqual({'hypervisor': expected_dict}, result)
+ self.assertEqual(
+ 1,
+ self.controller.host_api.get_host_uptime.call_count
+ )
def test_show_old_version(self):
# ensure things still work as expected here
diff --git a/nova/tests/unit/api/openstack/compute/test_image_metadata.py b/nova/tests/unit/api/openstack/compute/test_image_metadata.py
index 2e1c26a712..4072d6f489 100644
--- a/nova/tests/unit/api/openstack/compute/test_image_metadata.py
+++ b/nova/tests/unit/api/openstack/compute/test_image_metadata.py
@@ -14,8 +14,8 @@
# under the License.
import copy
+from unittest import mock
-import mock
from oslo_serialization import jsonutils
import webob
diff --git a/nova/tests/unit/api/openstack/compute/test_images.py b/nova/tests/unit/api/openstack/compute/test_images.py
index fad4fcb5a2..734e755dd5 100644
--- a/nova/tests/unit/api/openstack/compute/test_images.py
+++ b/nova/tests/unit/api/openstack/compute/test_images.py
@@ -19,9 +19,9 @@ and as a WSGI layer
"""
import copy
+from unittest import mock
from urllib import parse as urlparse
-import mock
import webob
from nova.api.openstack.compute import images as images_v21
diff --git a/nova/tests/unit/api/openstack/compute/test_instance_actions.py b/nova/tests/unit/api/openstack/compute/test_instance_actions.py
index 04e9ae443e..df13e1d89d 100644
--- a/nova/tests/unit/api/openstack/compute/test_instance_actions.py
+++ b/nova/tests/unit/api/openstack/compute/test_instance_actions.py
@@ -15,9 +15,9 @@
import copy
import datetime
+from unittest import mock
import iso8601
-import mock
from oslo_policy import policy as oslo_policy
from oslo_utils.fixture import uuidsentinel as uuids
from webob import exc
diff --git a/nova/tests/unit/api/openstack/compute/test_keypairs.py b/nova/tests/unit/api/openstack/compute/test_keypairs.py
index 657973ffbd..590639d5ed 100644
--- a/nova/tests/unit/api/openstack/compute/test_keypairs.py
+++ b/nova/tests/unit/api/openstack/compute/test_keypairs.py
@@ -13,7 +13,8 @@
# License for the specific language governing permissions and limitations
# under the License.
-import mock
+from unittest import mock
+
import webob
from nova.api.openstack.compute import keypairs as keypairs_v21
@@ -37,6 +38,8 @@ keypair_data = {
FAKE_UUID = 'b48316c5-71e8-45e4-9884-6c78055b9b13'
+keypair_name_2_92_compatible = 'my-key@ my.host'
+
def fake_keypair(name):
return dict(test_keypair.fake_keypair,
@@ -110,16 +113,22 @@ class KeypairsTestV21(test.TestCase):
self.assertGreater(len(res_dict['keypair']['private_key']), 0)
self._assert_keypair_type(res_dict)
- def _test_keypair_create_bad_request_case(self,
- body,
- exception):
- self.assertRaises(exception,
- self.controller.create, self.req, body=body)
+ def _test_keypair_create_bad_request_case(
+ self, body, exception, error_msg=None
+ ):
+ if error_msg:
+ self.assertRaisesRegex(exception, error_msg,
+ self.controller.create,
+ self.req, body=body)
+ else:
+ self.assertRaises(exception,
+ self.controller.create, self.req, body=body)
def test_keypair_create_with_empty_name(self):
body = {'keypair': {'name': ''}}
self._test_keypair_create_bad_request_case(body,
- self.validation_error)
+ self.validation_error,
+ 'is too short')
def test_keypair_create_with_name_too_long(self):
body = {
@@ -128,7 +137,8 @@ class KeypairsTestV21(test.TestCase):
}
}
self._test_keypair_create_bad_request_case(body,
- self.validation_error)
+ self.validation_error,
+ 'is too long')
def test_keypair_create_with_name_leading_trailing_spaces(self):
body = {
@@ -136,8 +146,10 @@ class KeypairsTestV21(test.TestCase):
'name': ' test '
}
}
+ expected_msg = 'Can not start or end with whitespace.'
self._test_keypair_create_bad_request_case(body,
- self.validation_error)
+ self.validation_error,
+ expected_msg)
def test_keypair_create_with_name_leading_trailing_spaces_compat_mode(
self):
@@ -152,8 +164,21 @@ class KeypairsTestV21(test.TestCase):
'name': 'test/keypair'
}
}
+ expected_msg = 'Only expected characters'
self._test_keypair_create_bad_request_case(body,
- webob.exc.HTTPBadRequest)
+ self.validation_error,
+ expected_msg)
+
+ def test_keypair_create_with_special_characters(self):
+ body = {
+ 'keypair': {
+ 'name': keypair_name_2_92_compatible
+ }
+ }
+ expected_msg = 'Only expected characters'
+ self._test_keypair_create_bad_request_case(body,
+ self.validation_error,
+ expected_msg)
def test_keypair_import_bad_key(self):
body = {
@@ -167,8 +192,10 @@ class KeypairsTestV21(test.TestCase):
def test_keypair_create_with_invalid_keypair_body(self):
body = {'alpha': {'name': 'create_test'}}
+ expected_msg = "'keypair' is a required property"
self._test_keypair_create_bad_request_case(body,
- self.validation_error)
+ self.validation_error,
+ expected_msg)
def test_keypair_import(self):
body = {
@@ -228,50 +255,6 @@ class KeypairsTestV21(test.TestCase):
self.controller.create, self.req, body=body)
self.assertIn('Quota exceeded, too many key pairs.', ex.explanation)
- @mock.patch('nova.objects.Quotas.check_deltas')
- def test_keypair_create_over_quota_during_recheck(self, mock_check):
- # Simulate a race where the first check passes and the recheck fails.
- # First check occurs in compute/api.
- exc = exception.OverQuota(overs='key_pairs', usages={'key_pairs': 100})
- mock_check.side_effect = [None, exc]
- body = {
- 'keypair': {
- 'name': 'FAKE',
- },
- }
-
- self.assertRaises(webob.exc.HTTPForbidden,
- self.controller.create, self.req, body=body)
-
- ctxt = self.req.environ['nova.context']
- self.assertEqual(2, mock_check.call_count)
- call1 = mock.call(ctxt, {'key_pairs': 1}, ctxt.user_id)
- call2 = mock.call(ctxt, {'key_pairs': 0}, ctxt.user_id)
- mock_check.assert_has_calls([call1, call2])
-
- # Verify we removed the key pair that was added after the first
- # quota check passed.
- key_pairs = objects.KeyPairList.get_by_user(ctxt, ctxt.user_id)
- names = [key_pair.name for key_pair in key_pairs]
- self.assertNotIn('create_test', names)
-
- @mock.patch('nova.objects.Quotas.check_deltas')
- def test_keypair_create_no_quota_recheck(self, mock_check):
- # Disable recheck_quota.
- self.flags(recheck_quota=False, group='quota')
-
- body = {
- 'keypair': {
- 'name': 'create_test',
- },
- }
- self.controller.create(self.req, body=body)
-
- ctxt = self.req.environ['nova.context']
- # check_deltas should have been called only once.
- mock_check.assert_called_once_with(ctxt, {'key_pairs': 1},
- ctxt.user_id)
-
def test_keypair_create_duplicate(self):
self.stub_out("nova.objects.KeyPair.create",
db_key_pair_create_duplicate)
@@ -514,3 +497,82 @@ class KeypairsTestV275(test.TestCase):
version='2.75', use_admin_context=True)
self.assertRaises(exception.ValidationError, self.controller.delete,
req, 1)
+
+
+class KeypairsTestV292(test.TestCase):
+ wsgi_api_version = '2.92'
+ wsgi_old_api_version = '2.91'
+
+ def setUp(self):
+ super(KeypairsTestV292, self).setUp()
+ self.controller = keypairs_v21.KeypairController()
+ self.req = fakes.HTTPRequest.blank('', version=self.wsgi_api_version)
+ self.old_req = fakes.HTTPRequest.blank(
+ '', version=self.wsgi_old_api_version)
+
+ def test_keypair_create_no_longer_supported(self):
+ body = {
+ 'keypair': {
+ 'name': keypair_name_2_92_compatible,
+ }
+ }
+ self.assertRaises(exception.ValidationError, self.controller.create,
+ self.req, body=body)
+
+ def test_keypair_create_works_with_old_version(self):
+ body = {
+ 'keypair': {
+ 'name': 'fake',
+ }
+ }
+ res_dict = self.controller.create(self.old_req, body=body)
+ self.assertEqual('fake', res_dict['keypair']['name'])
+ self.assertGreater(len(res_dict['keypair']['private_key']), 0)
+
+ def test_keypair_import_works_with_new_version(self):
+ body = {
+ 'keypair': {
+ 'name': 'fake',
+ 'public_key': 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDBYIznA'
+ 'x9D7118Q1VKGpXy2HDiKyUTM8XcUuhQpo0srqb9rboUp4'
+ 'a9NmCwpWpeElDLuva707GOUnfaBAvHBwsRXyxHJjRaI6Y'
+ 'Qj2oLJwqvaSaWUbyT1vtryRqy6J3TecN0WINY71f4uymi'
+ 'MZP0wby4bKBcYnac8KiCIlvkEl0ETjkOGUq8OyWRmn7lj'
+ 'j5SESEUdBP0JnuTFKddWTU/wD6wydeJaUhBTqOlHn0kX1'
+ 'GyqoNTE1UEhcM5ZRWgfUZfTjVyDF2kGj3vJLCJtJ8LoGc'
+ 'j7YaN4uPg1rBle+izwE/tLonRrds+cev8p6krSSrxWOwB'
+ 'bHkXa6OciiJDvkRzJXzf',
+ }
+ }
+ res_dict = self.controller.create(self.req, body=body)
+ self.assertEqual('fake', res_dict['keypair']['name'])
+ self.assertNotIn('private_key', res_dict['keypair'])
+
+ def test_keypair_create_refuses_special_chars_with_old_version(self):
+ body = {
+ 'keypair': {
+ 'name': keypair_name_2_92_compatible,
+ }
+ }
+ self.assertRaises(exception.ValidationError, self.controller.create,
+ self.old_req, body=body)
+
+ def test_keypair_import_with_special_characters(self):
+ body = {
+ 'keypair': {
+ 'name': keypair_name_2_92_compatible,
+ 'public_key': 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDBYIznA'
+ 'x9D7118Q1VKGpXy2HDiKyUTM8XcUuhQpo0srqb9rboUp4'
+ 'a9NmCwpWpeElDLuva707GOUnfaBAvHBwsRXyxHJjRaI6Y'
+ 'Qj2oLJwqvaSaWUbyT1vtryRqy6J3TecN0WINY71f4uymi'
+ 'MZP0wby4bKBcYnac8KiCIlvkEl0ETjkOGUq8OyWRmn7lj'
+ 'j5SESEUdBP0JnuTFKddWTU/wD6wydeJaUhBTqOlHn0kX1'
+ 'GyqoNTE1UEhcM5ZRWgfUZfTjVyDF2kGj3vJLCJtJ8LoGc'
+ 'j7YaN4uPg1rBle+izwE/tLonRrds+cev8p6krSSrxWOwB'
+ 'bHkXa6OciiJDvkRzJXzf',
+ }
+ }
+
+ res_dict = self.controller.create(self.req, body=body)
+ self.assertEqual(keypair_name_2_92_compatible,
+ res_dict['keypair']['name'])
diff --git a/nova/tests/unit/api/openstack/compute/test_limits.py b/nova/tests/unit/api/openstack/compute/test_limits.py
index 31033e111d..1748023aa8 100644
--- a/nova/tests/unit/api/openstack/compute/test_limits.py
+++ b/nova/tests/unit/api/openstack/compute/test_limits.py
@@ -19,8 +19,9 @@ Tests dealing with HTTP rate-limiting.
from http import client as httplib
from io import StringIO
+from unittest import mock
-import mock
+from oslo_limit import fixture as limit_fixture
from oslo_serialization import jsonutils
from oslo_utils import encodeutils
@@ -29,8 +30,10 @@ from nova.api.openstack.compute import views
from nova.api.openstack import wsgi
import nova.context
from nova import exception
+from nova.limit import local as local_limit
+from nova.limit import placement as placement_limit
+from nova import objects
from nova.policies import limits as l_policies
-from nova import quota
from nova import test
from nova.tests.unit.api.openstack import fakes
from nova.tests.unit import matchers
@@ -48,12 +51,12 @@ class BaseLimitTestSuite(test.NoDBTestCase):
return {k: dict(limit=v, in_use=v // 2)
for k, v in self.absolute_limits.items()}
- mock_get_project_quotas = mock.patch.object(
+ patcher_get_project_quotas = mock.patch.object(
nova.quota.QUOTAS,
"get_project_quotas",
- side_effect = stub_get_project_quotas)
- mock_get_project_quotas.start()
- self.addCleanup(mock_get_project_quotas.stop)
+ side_effect=stub_get_project_quotas)
+ self.mock_get_project_quotas = patcher_get_project_quotas.start()
+ self.addCleanup(patcher_get_project_quotas.stop)
patcher = self.mock_can = mock.patch('nova.context.RequestContext.can')
self.mock_can = patcher.start()
self.addCleanup(patcher.stop)
@@ -150,16 +153,14 @@ class LimitsControllerTestV21(BaseLimitTestSuite):
return {k: dict(limit=v, in_use=v // 2)
for k, v in self.absolute_limits.items()}
- with mock.patch('nova.quota.QUOTAS.get_project_quotas') as \
- get_project_quotas:
- get_project_quotas.side_effect = _get_project_quotas
+ self.mock_get_project_quotas.side_effect = _get_project_quotas
- response = request.get_response(self.controller)
+ response = request.get_response(self.controller)
- body = jsonutils.loads(response.body)
- self.assertEqual(expected, body)
- get_project_quotas.assert_called_once_with(context, tenant_id,
- usages=True)
+ body = jsonutils.loads(response.body)
+ self.assertEqual(expected, body)
+ self.mock_get_project_quotas.assert_called_once_with(
+ context, tenant_id, usages=True)
def _do_test_used_limits(self, reserved):
request = self._get_index_request(tenant_id=None)
@@ -182,8 +183,7 @@ class LimitsControllerTestV21(BaseLimitTestSuite):
def stub_get_project_quotas(context, project_id, usages=True):
return limits
- self.stub_out('nova.quota.QUOTAS.get_project_quotas',
- stub_get_project_quotas)
+ self.mock_get_project_quotas.side_effect = stub_get_project_quotas
res = request.get_response(self.controller)
body = jsonutils.loads(res.body)
@@ -207,15 +207,15 @@ class LimitsControllerTestV21(BaseLimitTestSuite):
user_id=user_id,
project_id=project_id)
context = fake_req.environ["nova.context"]
- with mock.patch.object(quota.QUOTAS, 'get_project_quotas',
- return_value={}) as mock_get_quotas:
- fake_req.get_response(self.controller)
- self.assertEqual(2, self.mock_can.call_count)
- self.mock_can.assert_called_with(
- l_policies.OTHER_PROJECT_LIMIT_POLICY_NAME,
- target={"project_id": tenant_id})
- mock_get_quotas.assert_called_once_with(context,
- tenant_id, usages=True)
+ self.mock_get_project_quotas.side_effect = None
+ self.mock_get_project_quotas.return_value = {}
+
+ fake_req.get_response(self.controller)
+ self.assertEqual(2, self.mock_can.call_count)
+ self.mock_can.assert_called_with(
+ l_policies.OTHER_PROJECT_LIMIT_POLICY_NAME)
+ self.mock_get_project_quotas.assert_called_once_with(context,
+ tenant_id, usages=True)
def _test_admin_can_fetch_used_limits_for_own_project(self, req_get):
project_id = "123456"
@@ -227,11 +227,12 @@ class LimitsControllerTestV21(BaseLimitTestSuite):
project_id=project_id)
context = fake_req.environ["nova.context"]
- with mock.patch.object(quota.QUOTAS, 'get_project_quotas',
- return_value={}) as mock_get_quotas:
- fake_req.get_response(self.controller)
- mock_get_quotas.assert_called_once_with(context,
- project_id, usages=True)
+ self.mock_get_project_quotas.side_effect = None
+ self.mock_get_project_quotas.return_value = {}
+
+ fake_req.get_response(self.controller)
+ self.mock_get_project_quotas.assert_called_once_with(
+ context, project_id, usages=True)
def test_admin_can_fetch_used_limits_for_own_project(self):
req_get = {}
@@ -251,7 +252,7 @@ class LimitsControllerTestV21(BaseLimitTestSuite):
req_get = {'tenant_id': -1}
self._test_admin_can_fetch_used_limits_for_own_project(req_get)
- def test_admin_can_fetch_used_limits_with_unkown_param(self):
+ def test_admin_can_fetch_used_limits_with_unknown_param(self):
req_get = {'tenant_id': '123', 'unknown': 'unknown'}
self._test_admin_can_fetch_used_limits_for_own_project(req_get)
@@ -259,12 +260,13 @@ class LimitsControllerTestV21(BaseLimitTestSuite):
project_id = "123456"
fake_req = self._get_index_request(project_id=project_id)
context = fake_req.environ["nova.context"]
- with mock.patch.object(quota.QUOTAS, 'get_project_quotas',
- return_value={}) as mock_get_quotas:
- fake_req.get_response(self.controller)
+ self.mock_get_project_quotas.side_effect = None
+ self.mock_get_project_quotas.return_value = {}
- mock_get_quotas.assert_called_once_with(context,
- project_id, usages=True)
+ fake_req.get_response(self.controller)
+
+ self.mock_get_project_quotas.assert_called_once_with(
+ context, project_id, usages=True)
def test_used_ram_added(self):
fake_req = self._get_index_request()
@@ -272,28 +274,26 @@ class LimitsControllerTestV21(BaseLimitTestSuite):
def stub_get_project_quotas(context, project_id, usages=True):
return {'ram': {'limit': 512, 'in_use': 256}}
- with mock.patch.object(quota.QUOTAS, 'get_project_quotas',
- side_effect=stub_get_project_quotas
- ) as mock_get_quotas:
+ self.mock_get_project_quotas.side_effect = stub_get_project_quotas
- res = fake_req.get_response(self.controller)
- body = jsonutils.loads(res.body)
- abs_limits = body['limits']['absolute']
- self.assertIn('totalRAMUsed', abs_limits)
- self.assertEqual(256, abs_limits['totalRAMUsed'])
- self.assertEqual(1, mock_get_quotas.call_count)
+ res = fake_req.get_response(self.controller)
+ body = jsonutils.loads(res.body)
+ abs_limits = body['limits']['absolute']
+ self.assertIn('totalRAMUsed', abs_limits)
+ self.assertEqual(256, abs_limits['totalRAMUsed'])
+ self.assertEqual(1, self.mock_get_project_quotas.call_count)
def test_no_ram_quota(self):
fake_req = self._get_index_request()
- with mock.patch.object(quota.QUOTAS, 'get_project_quotas',
- return_value={}) as mock_get_quotas:
+ self.mock_get_project_quotas.side_effect = None
+ self.mock_get_project_quotas.return_value = {}
- res = fake_req.get_response(self.controller)
- body = jsonutils.loads(res.body)
- abs_limits = body['limits']['absolute']
- self.assertNotIn('totalRAMUsed', abs_limits)
- self.assertEqual(1, mock_get_quotas.call_count)
+ res = fake_req.get_response(self.controller)
+ body = jsonutils.loads(res.body)
+ abs_limits = body['limits']['absolute']
+ self.assertNotIn('totalRAMUsed', abs_limits)
+ self.assertEqual(1, self.mock_get_project_quotas.call_count)
class FakeHttplibSocket(object):
@@ -395,25 +395,24 @@ class LimitsControllerTestV236(BaseLimitTestSuite):
return {k: dict(limit=v, in_use=v // 2)
for k, v in absolute_limits.items()}
- with mock.patch('nova.quota.QUOTAS.get_project_quotas') as \
- get_project_quotas:
- get_project_quotas.side_effect = _get_project_quotas
- response = self.controller.index(self.req)
- expected_response = {
- "limits": {
- "rate": [],
- "absolute": {
- "maxTotalRAMSize": 512,
- "maxTotalInstances": 5,
- "maxTotalCores": 21,
- "maxTotalKeypairs": 10,
- "totalRAMUsed": 256,
- "totalCoresUsed": 10,
- "totalInstancesUsed": 2,
- },
+ self.mock_get_project_quotas.side_effect = _get_project_quotas
+
+ response = self.controller.index(self.req)
+ expected_response = {
+ "limits": {
+ "rate": [],
+ "absolute": {
+ "maxTotalRAMSize": 512,
+ "maxTotalInstances": 5,
+ "maxTotalCores": 21,
+ "maxTotalKeypairs": 10,
+ "totalRAMUsed": 256,
+ "totalCoresUsed": 10,
+ "totalInstancesUsed": 2,
},
- }
- self.assertEqual(expected_response, response)
+ },
+ }
+ self.assertEqual(expected_response, response)
class LimitsControllerTestV239(BaseLimitTestSuite):
@@ -433,21 +432,20 @@ class LimitsControllerTestV239(BaseLimitTestSuite):
return {k: dict(limit=v, in_use=v // 2)
for k, v in absolute_limits.items()}
- with mock.patch('nova.quota.QUOTAS.get_project_quotas') as \
- get_project_quotas:
- get_project_quotas.side_effect = _get_project_quotas
- response = self.controller.index(self.req)
- # staring from version 2.39 there is no 'maxImageMeta' field
- # in response after removing 'image-metadata' proxy API
- expected_response = {
- "limits": {
- "rate": [],
- "absolute": {
- "maxServerMeta": 1,
- },
+ self.mock_get_project_quotas.side_effect = _get_project_quotas
+
+ response = self.controller.index(self.req)
+ # starting from version 2.39 there is no 'maxImageMeta' field
+ # in response after removing 'image-metadata' proxy API
+ expected_response = {
+ "limits": {
+ "rate": [],
+ "absolute": {
+ "maxServerMeta": 1,
},
- }
- self.assertEqual(expected_response, response)
+ },
+ }
+ self.assertEqual(expected_response, response)
class LimitsControllerTestV275(BaseLimitTestSuite):
@@ -459,21 +457,170 @@ class LimitsControllerTestV275(BaseLimitTestSuite):
absolute_limits = {
"metadata_items": 1,
}
- req = fakes.HTTPRequest.blank("/?unkown=fake",
+ req = fakes.HTTPRequest.blank("/?unknown=fake",
version='2.74')
def _get_project_quotas(context, project_id, usages=True):
return {k: dict(limit=v, in_use=v // 2)
for k, v in absolute_limits.items()}
- with mock.patch('nova.quota.QUOTAS.get_project_quotas') as \
- get_project_quotas:
- get_project_quotas.side_effect = _get_project_quotas
- self.controller.index(req)
+ self.mock_get_project_quotas.side_effect = _get_project_quotas
+ self.controller.index(req)
+ self.controller.index(req)
def test_index_additional_query_param(self):
- req = fakes.HTTPRequest.blank("/?unkown=fake",
+ req = fakes.HTTPRequest.blank("/?unknown=fake",
version='2.75')
self.assertRaises(
exception.ValidationError,
self.controller.index, req=req)
+
+
+class NoopLimitsControllerTest(test.NoDBTestCase):
+ quota_driver = "nova.quota.NoopQuotaDriver"
+
+ def setUp(self):
+ super(NoopLimitsControllerTest, self).setUp()
+ self.flags(driver=self.quota_driver, group="quota")
+ self.controller = limits_v21.LimitsController()
+ # remove policy checks
+ patcher = self.mock_can = mock.patch('nova.context.RequestContext.can')
+ self.mock_can = patcher.start()
+ self.addCleanup(patcher.stop)
+
+ def test_index_v21(self):
+ req = fakes.HTTPRequest.blank("/")
+ response = self.controller.index(req)
+ expected_response = {
+ "limits": {
+ "rate": [],
+ "absolute": {
+ 'maxImageMeta': -1,
+ 'maxPersonality': -1,
+ 'maxPersonalitySize': -1,
+ 'maxSecurityGroupRules': -1,
+ 'maxSecurityGroups': -1,
+ 'maxServerGroupMembers': -1,
+ 'maxServerGroups': -1,
+ 'maxServerMeta': -1,
+ 'maxTotalCores': -1,
+ 'maxTotalFloatingIps': -1,
+ 'maxTotalInstances': -1,
+ 'maxTotalKeypairs': -1,
+ 'maxTotalRAMSize': -1,
+ 'totalCoresUsed': -1,
+ 'totalFloatingIpsUsed': -1,
+ 'totalInstancesUsed': -1,
+ 'totalRAMUsed': -1,
+ 'totalSecurityGroupsUsed': -1,
+ 'totalServerGroupsUsed': -1,
+ },
+ },
+ }
+ self.assertEqual(expected_response, response)
+
+ def test_index_v275(self):
+ req = fakes.HTTPRequest.blank("/?tenant_id=faketenant",
+ version='2.75')
+ response = self.controller.index(req)
+ expected_response = {
+ "limits": {
+ "rate": [],
+ "absolute": {
+ 'maxServerGroupMembers': -1,
+ 'maxServerGroups': -1,
+ 'maxServerMeta': -1,
+ 'maxTotalCores': -1,
+ 'maxTotalInstances': -1,
+ 'maxTotalKeypairs': -1,
+ 'maxTotalRAMSize': -1,
+ 'totalCoresUsed': -1,
+ 'totalInstancesUsed': -1,
+ 'totalRAMUsed': -1,
+ 'totalServerGroupsUsed': -1,
+ },
+ },
+ }
+ self.assertEqual(expected_response, response)
+
+
+class UnifiedLimitsControllerTest(NoopLimitsControllerTest):
+ quota_driver = "nova.quota.UnifiedLimitsDriver"
+
+ def setUp(self):
+ super(UnifiedLimitsControllerTest, self).setUp()
+ reglimits = {local_limit.SERVER_METADATA_ITEMS: 128,
+ local_limit.INJECTED_FILES: 5,
+ local_limit.INJECTED_FILES_CONTENT: 10 * 1024,
+ local_limit.INJECTED_FILES_PATH: 255,
+ local_limit.KEY_PAIRS: 100,
+ local_limit.SERVER_GROUPS: 12,
+ local_limit.SERVER_GROUP_MEMBERS: 10}
+ self.useFixture(limit_fixture.LimitFixture(reglimits, {}))
+
+ @mock.patch.object(placement_limit, "get_legacy_counts")
+ @mock.patch.object(placement_limit, "get_legacy_project_limits")
+ @mock.patch.object(objects.InstanceGroupList, "get_counts")
+ def test_index_v21(self, mock_count, mock_proj, mock_kcount):
+ mock_proj.return_value = {"instances": 1, "cores": 2, "ram": 3}
+ mock_kcount.return_value = {"instances": 4, "cores": 5, "ram": 6}
+ mock_count.return_value = {'project': {'server_groups': 9}}
+ req = fakes.HTTPRequest.blank("/")
+ response = self.controller.index(req)
+ expected_response = {
+ "limits": {
+ "rate": [],
+ "absolute": {
+ 'maxImageMeta': 128,
+ 'maxPersonality': 5,
+ 'maxPersonalitySize': 10240,
+ 'maxSecurityGroupRules': -1,
+ 'maxSecurityGroups': -1,
+ 'maxServerGroupMembers': 10,
+ 'maxServerGroups': 12,
+ 'maxServerMeta': 128,
+ 'maxTotalCores': 2,
+ 'maxTotalFloatingIps': -1,
+ 'maxTotalInstances': 1,
+ 'maxTotalKeypairs': 100,
+ 'maxTotalRAMSize': 3,
+ 'totalCoresUsed': 5,
+ 'totalFloatingIpsUsed': 0,
+ 'totalInstancesUsed': 4,
+ 'totalRAMUsed': 6,
+ 'totalSecurityGroupsUsed': 0,
+ 'totalServerGroupsUsed': 9,
+ },
+ },
+ }
+ self.assertEqual(expected_response, response)
+
+ @mock.patch.object(placement_limit, "get_legacy_counts")
+ @mock.patch.object(placement_limit, "get_legacy_project_limits")
+ @mock.patch.object(objects.InstanceGroupList, "get_counts")
+ def test_index_v275(self, mock_count, mock_proj, mock_kcount):
+ mock_proj.return_value = {"instances": 1, "cores": 2, "ram": 3}
+ mock_kcount.return_value = {"instances": 4, "cores": 5, "ram": 6}
+ mock_count.return_value = {'project': {'server_groups': 9}}
+ req = fakes.HTTPRequest.blank("/?tenant_id=faketenant",
+ version='2.75')
+ response = self.controller.index(req)
+ expected_response = {
+ "limits": {
+ "rate": [],
+ "absolute": {
+ 'maxServerGroupMembers': 10,
+ 'maxServerGroups': 12,
+ 'maxServerMeta': 128,
+ 'maxTotalCores': 2,
+ 'maxTotalInstances': 1,
+ 'maxTotalKeypairs': 100,
+ 'maxTotalRAMSize': 3,
+ 'totalCoresUsed': 5,
+ 'totalInstancesUsed': 4,
+ 'totalRAMUsed': 6,
+ 'totalServerGroupsUsed': 9,
+ },
+ },
+ }
+ self.assertEqual(expected_response, response)
diff --git a/nova/tests/unit/api/openstack/compute/test_lock_server.py b/nova/tests/unit/api/openstack/compute/test_lock_server.py
index a605e2bcdb..bf49bf2b73 100644
--- a/nova/tests/unit/api/openstack/compute/test_lock_server.py
+++ b/nova/tests/unit/api/openstack/compute/test_lock_server.py
@@ -13,7 +13,7 @@
# License for the specific language governing permissions and limitations
# under the License.
-import mock
+from unittest import mock
from nova.api.openstack import api_version_request
from nova.api.openstack import common
@@ -114,7 +114,7 @@ class LockServerTestsV273(LockServerTestsV21):
self.controller._lock, self.req, instance.uuid, body=body)
self.assertIn("256 is not of type 'string'", str(exp))
- def test_lock_with_invalid_paramater(self):
+ def test_lock_with_invalid_parameter(self):
# This will fail from 2.73 since we have a schema check that allows
# only locked_reason
instance = fake_instance.fake_instance_obj(
diff --git a/nova/tests/unit/api/openstack/compute/test_microversions.py b/nova/tests/unit/api/openstack/compute/test_microversions.py
index c5b1ddb5e5..9f5dd90889 100644
--- a/nova/tests/unit/api/openstack/compute/test_microversions.py
+++ b/nova/tests/unit/api/openstack/compute/test_microversions.py
@@ -12,7 +12,8 @@
# License for the specific language governing permissions and limitations
# under the License.
-import mock
+from unittest import mock
+
from oslo_serialization import jsonutils
from nova.api.openstack import api_version_request as api_version
diff --git a/nova/tests/unit/api/openstack/compute/test_migrate_server.py b/nova/tests/unit/api/openstack/compute/test_migrate_server.py
index 683759eccc..8d1c853206 100644
--- a/nova/tests/unit/api/openstack/compute/test_migrate_server.py
+++ b/nova/tests/unit/api/openstack/compute/test_migrate_server.py
@@ -13,8 +13,9 @@
# License for the specific language governing permissions and limitations
# under the License.
+from unittest import mock
+
import fixtures
-import mock
from oslo_utils.fixture import uuidsentinel as uuids
from oslo_utils import uuidutils
import webob
@@ -530,9 +531,8 @@ class MigrateServerTestsV256(MigrateServerTestsV234):
self.req, fakes.FAKE_UUID, body=body)
def _test_migrate_exception(self, exc_info, expected_result):
- @mock.patch.object(self.compute_api, 'get')
@mock.patch.object(self.compute_api, 'resize', side_effect=exc_info)
- def _test(mock_resize, mock_get):
+ def _test(mock_resize):
instance = objects.Instance(uuid=uuids.instance)
self.assertRaises(expected_result,
self.controller._migrate,
diff --git a/nova/tests/unit/api/openstack/compute/test_migrations.py b/nova/tests/unit/api/openstack/compute/test_migrations.py
index a06d395bea..19bc42a9de 100644
--- a/nova/tests/unit/api/openstack/compute/test_migrations.py
+++ b/nova/tests/unit/api/openstack/compute/test_migrations.py
@@ -13,9 +13,9 @@
# under the License.
import datetime
+from unittest import mock
import iso8601
-import mock
from oslo_utils.fixture import uuidsentinel as uuids
from webob import exc
diff --git a/nova/tests/unit/api/openstack/compute/test_multinic.py b/nova/tests/unit/api/openstack/compute/test_multinic.py
index ceaaebf373..17a872fed2 100644
--- a/nova/tests/unit/api/openstack/compute/test_multinic.py
+++ b/nova/tests/unit/api/openstack/compute/test_multinic.py
@@ -13,8 +13,9 @@
# License for the specific language governing permissions and limitations
# under the License.
+from unittest import mock
+
import fixtures
-import mock
import webob
from nova.api.openstack.compute import multinic as multinic_v21
diff --git a/nova/tests/unit/api/openstack/compute/test_networks.py b/nova/tests/unit/api/openstack/compute/test_networks.py
index 595353e7b1..bcbce58483 100644
--- a/nova/tests/unit/api/openstack/compute/test_networks.py
+++ b/nova/tests/unit/api/openstack/compute/test_networks.py
@@ -26,7 +26,7 @@ from nova import test
from nova.tests.unit.api.openstack import fakes
-# NOTE(stephenfin): obviously these aren't complete reponses, but this is all
+# NOTE(stephenfin): obviously these aren't complete responses, but this is all
# we care about
FAKE_NETWORKS = [
{
diff --git a/nova/tests/unit/api/openstack/compute/test_quota_classes.py b/nova/tests/unit/api/openstack/compute/test_quota_classes.py
index bdb33a7e1a..463f8344c0 100644
--- a/nova/tests/unit/api/openstack/compute/test_quota_classes.py
+++ b/nova/tests/unit/api/openstack/compute/test_quota_classes.py
@@ -12,12 +12,19 @@
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
+
import copy
+from unittest import mock
+
+from oslo_limit import fixture as limit_fixture
import webob
from nova.api.openstack.compute import quota_classes \
as quota_classes_v21
from nova import exception
+from nova.limit import local as local_limit
+from nova.limit import placement as placement_limit
+from nova import objects
from nova import test
from nova.tests.unit.api.openstack import fakes
@@ -156,3 +163,220 @@ class QuotaClassSetsTestV257(QuotaClassSetsTestV250):
for resource in quota_classes_v21.FILTERED_QUOTAS_2_57:
self.quota_resources.pop(resource, None)
self.filtered_quotas.extend(quota_classes_v21.FILTERED_QUOTAS_2_57)
+
+
+class NoopQuotaClassesTest(test.NoDBTestCase):
+ quota_driver = "nova.quota.NoopQuotaDriver"
+
+ def setUp(self):
+ super(NoopQuotaClassesTest, self).setUp()
+ self.flags(driver=self.quota_driver, group="quota")
+ self.controller = quota_classes_v21.QuotaClassSetsController()
+
+ def test_show_v21(self):
+ req = fakes.HTTPRequest.blank("")
+ response = self.controller.show(req, "test_class")
+ expected_response = {
+ 'quota_class_set': {
+ 'id': 'test_class',
+ 'cores': -1,
+ 'fixed_ips': -1,
+ 'floating_ips': -1,
+ 'injected_file_content_bytes': -1,
+ 'injected_file_path_bytes': -1,
+ 'injected_files': -1,
+ 'instances': -1,
+ 'key_pairs': -1,
+ 'metadata_items': -1,
+ 'ram': -1,
+ 'security_group_rules': -1,
+ 'security_groups': -1
+ }
+ }
+ self.assertEqual(expected_response, response)
+
+ def test_show_v257(self):
+ req = fakes.HTTPRequest.blank("", version='2.57')
+ response = self.controller.show(req, "default")
+ expected_response = {
+ 'quota_class_set': {
+ 'id': 'default',
+ 'cores': -1,
+ 'instances': -1,
+ 'key_pairs': -1,
+ 'metadata_items': -1,
+ 'ram': -1,
+ 'server_group_members': -1,
+ 'server_groups': -1,
+ }
+ }
+ self.assertEqual(expected_response, response)
+
+ def test_update_v21_still_rejects_badrequests(self):
+ req = fakes.HTTPRequest.blank("")
+ body = {'quota_class_set': {'instances': 50, 'cores': 50,
+ 'ram': 51200, 'unsupported': 12}}
+ self.assertRaises(exception.ValidationError, self.controller.update,
+ req, 'test_class', body=body)
+
+ @mock.patch.object(objects.Quotas, "update_class")
+ def test_update_v21(self, mock_update):
+ req = fakes.HTTPRequest.blank("")
+ body = {'quota_class_set': {'ram': 51200}}
+ response = self.controller.update(req, 'default', body=body)
+ expected_response = {
+ 'quota_class_set': {
+ 'cores': -1,
+ 'fixed_ips': -1,
+ 'floating_ips': -1,
+ 'injected_file_content_bytes': -1,
+ 'injected_file_path_bytes': -1,
+ 'injected_files': -1,
+ 'instances': -1,
+ 'key_pairs': -1,
+ 'metadata_items': -1,
+ 'ram': -1,
+ 'security_group_rules': -1,
+ 'security_groups': -1
+ }
+ }
+ self.assertEqual(expected_response, response)
+ mock_update.assert_called_once_with(req.environ['nova.context'],
+ "default", "ram", 51200)
+
+ @mock.patch.object(objects.Quotas, "update_class")
+ def test_update_v257(self, mock_update):
+ req = fakes.HTTPRequest.blank("", version='2.57')
+ body = {'quota_class_set': {'ram': 51200}}
+ response = self.controller.update(req, 'default', body=body)
+ expected_response = {
+ 'quota_class_set': {
+ 'cores': -1,
+ 'instances': -1,
+ 'key_pairs': -1,
+ 'metadata_items': -1,
+ 'ram': -1,
+ 'server_group_members': -1,
+ 'server_groups': -1,
+ }
+ }
+ self.assertEqual(expected_response, response)
+ mock_update.assert_called_once_with(req.environ['nova.context'],
+ "default", "ram", 51200)
+
+
+class UnifiedLimitsQuotaClassesTest(NoopQuotaClassesTest):
+ quota_driver = "nova.quota.UnifiedLimitsDriver"
+
+ def setUp(self):
+ super(UnifiedLimitsQuotaClassesTest, self).setUp()
+ # Set server_groups so all config options get a different value
+ # but we also test as much as possible with the default config
+ self.flags(driver="nova.quota.UnifiedLimitsDriver", group='quota')
+ reglimits = {local_limit.SERVER_METADATA_ITEMS: 128,
+ local_limit.INJECTED_FILES: 5,
+ local_limit.INJECTED_FILES_CONTENT: 10 * 1024,
+ local_limit.INJECTED_FILES_PATH: 255,
+ local_limit.KEY_PAIRS: 100,
+ local_limit.SERVER_GROUPS: 12,
+ local_limit.SERVER_GROUP_MEMBERS: 10}
+ self.useFixture(limit_fixture.LimitFixture(reglimits, {}))
+
+ @mock.patch.object(placement_limit, "get_legacy_default_limits")
+ def test_show_v21(self, mock_default):
+ mock_default.return_value = {"instances": 1, "cores": 2, "ram": 3}
+ req = fakes.HTTPRequest.blank("")
+ response = self.controller.show(req, "test_class")
+ expected_response = {
+ 'quota_class_set': {
+ 'id': 'test_class',
+ 'cores': 2,
+ 'fixed_ips': -1,
+ 'floating_ips': -1,
+ 'ram': 3,
+ 'injected_file_content_bytes': 10240,
+ 'injected_file_path_bytes': 255,
+ 'injected_files': 5,
+ 'instances': 1,
+ 'key_pairs': 100,
+ 'metadata_items': 128,
+ 'security_group_rules': -1,
+ 'security_groups': -1,
+ }
+ }
+ self.assertEqual(expected_response, response)
+
+ @mock.patch.object(placement_limit, "get_legacy_default_limits")
+ def test_show_v257(self, mock_default):
+ mock_default.return_value = {"instances": 1, "cores": 2, "ram": 3}
+ req = fakes.HTTPRequest.blank("", version='2.57')
+ response = self.controller.show(req, "default")
+ expected_response = {
+ 'quota_class_set': {
+ 'id': 'default',
+ 'cores': 2,
+ 'instances': 1,
+ 'ram': 3,
+ 'key_pairs': 100,
+ 'metadata_items': 128,
+ 'server_group_members': 10,
+ 'server_groups': 12,
+ }
+ }
+ self.assertEqual(expected_response, response)
+
+ def test_update_still_rejects_badrequests(self):
+ req = fakes.HTTPRequest.blank("")
+ body = {'quota_class_set': {'instances': 50, 'cores': 50,
+ 'ram': 51200, 'unsupported': 12}}
+ self.assertRaises(exception.ValidationError, self.controller.update,
+ req, 'test_class', body=body)
+
+ @mock.patch.object(placement_limit, "get_legacy_default_limits")
+ @mock.patch.object(objects.Quotas, "update_class")
+ def test_update_v21(self, mock_update, mock_default):
+ mock_default.return_value = {"instances": 1, "cores": 2, "ram": 3}
+ req = fakes.HTTPRequest.blank("")
+ body = {'quota_class_set': {'ram': 51200}}
+ response = self.controller.update(req, 'default', body=body)
+ expected_response = {
+ 'quota_class_set': {
+ 'cores': 2,
+ 'fixed_ips': -1,
+ 'floating_ips': -1,
+ 'injected_file_content_bytes': 10240,
+ 'injected_file_path_bytes': 255,
+ 'injected_files': 5,
+ 'instances': 1,
+ 'key_pairs': 100,
+ 'metadata_items': 128,
+ 'ram': 3,
+ 'security_group_rules': -1,
+ 'security_groups': -1
+ }
+ }
+ self.assertEqual(expected_response, response)
+ # TODO(johngarbutt) we should be proxying to keystone
+ self.assertEqual(0, mock_update.call_count)
+
+ @mock.patch.object(placement_limit, "get_legacy_default_limits")
+ @mock.patch.object(objects.Quotas, "update_class")
+ def test_update_v257(self, mock_update, mock_default):
+ mock_default.return_value = {"instances": 1, "cores": 2, "ram": 3}
+ req = fakes.HTTPRequest.blank("", version='2.57')
+ body = {'quota_class_set': {'ram': 51200}}
+ response = self.controller.update(req, 'default', body=body)
+ expected_response = {
+ 'quota_class_set': {
+ 'cores': 2,
+ 'instances': 1,
+ 'ram': 3,
+ 'key_pairs': 100,
+ 'metadata_items': 128,
+ 'server_group_members': 10,
+ 'server_groups': 12,
+ }
+ }
+ self.assertEqual(expected_response, response)
+ # TODO(johngarbutt) we should be proxying to keystone
+ self.assertEqual(0, mock_update.call_count)
diff --git a/nova/tests/unit/api/openstack/compute/test_quotas.py b/nova/tests/unit/api/openstack/compute/test_quotas.py
index 545bd51e13..0a1bbd08d8 100644
--- a/nova/tests/unit/api/openstack/compute/test_quotas.py
+++ b/nova/tests/unit/api/openstack/compute/test_quotas.py
@@ -14,12 +14,18 @@
# License for the specific language governing permissions and limitations
# under the License.
-import mock
+from unittest import mock
+
+from oslo_limit import fixture as limit_fixture
+from oslo_utils.fixture import uuidsentinel as uuids
import webob
from nova.api.openstack.compute import quota_sets as quotas_v21
from nova.db import constants as db_const
from nova import exception
+from nova.limit import local as local_limit
+from nova.limit import placement as placement_limit
+from nova import objects
from nova import quota
from nova import test
from nova.tests.unit.api.openstack import fakes
@@ -660,3 +666,475 @@ class QuotaSetsTestV275(QuotaSetsTestV257):
query_string=query_string)
self.assertRaises(exception.ValidationError, self.controller.delete,
req, 1234)
+
+
+class NoopQuotaSetsTest(test.NoDBTestCase):
+ quota_driver = "nova.quota.NoopQuotaDriver"
+ expected_detail = {'in_use': -1, 'limit': -1, 'reserved': -1}
+
+ def setUp(self):
+ super(NoopQuotaSetsTest, self).setUp()
+ self.flags(driver=self.quota_driver, group="quota")
+ self.controller = quotas_v21.QuotaSetsController()
+ self.stub_out('nova.api.openstack.identity.verify_project_id',
+ lambda ctx, project_id: True)
+
+ def test_show_v21(self):
+ req = fakes.HTTPRequest.blank("")
+ response = self.controller.show(req, uuids.project_id)
+ expected_response = {
+ 'quota_set': {
+ 'id': uuids.project_id,
+ 'cores': -1,
+ 'fixed_ips': -1,
+ 'floating_ips': -1,
+ 'injected_file_content_bytes': -1,
+ 'injected_file_path_bytes': -1,
+ 'injected_files': -1,
+ 'instances': -1,
+ 'key_pairs': -1,
+ 'metadata_items': -1,
+ 'ram': -1,
+ 'security_group_rules': -1,
+ 'security_groups': -1,
+ 'server_group_members': -1,
+ 'server_groups': -1,
+ }
+ }
+ self.assertEqual(expected_response, response)
+
+ def test_show_v257(self):
+ req = fakes.HTTPRequest.blank("", version='2.57')
+ response = self.controller.show(req, uuids.project_id)
+ expected_response = {
+ 'quota_set': {
+ 'id': uuids.project_id,
+ 'cores': -1,
+ 'instances': -1,
+ 'key_pairs': -1,
+ 'metadata_items': -1,
+ 'ram': -1,
+ 'server_group_members': -1,
+ 'server_groups': -1}}
+ self.assertEqual(expected_response, response)
+
+ def test_detail_v21(self):
+ req = fakes.HTTPRequest.blank("")
+ response = self.controller.detail(req, uuids.project_id)
+
+ expected_response = {
+ 'quota_set': {
+ 'id': uuids.project_id,
+ 'cores': self.expected_detail,
+ 'fixed_ips': self.expected_detail,
+ 'floating_ips': self.expected_detail,
+ 'injected_file_content_bytes': self.expected_detail,
+ 'injected_file_path_bytes': self.expected_detail,
+ 'injected_files': self.expected_detail,
+ 'instances': self.expected_detail,
+ 'key_pairs': self.expected_detail,
+ 'metadata_items': self.expected_detail,
+ 'ram': self.expected_detail,
+ 'security_group_rules': self.expected_detail,
+ 'security_groups': self.expected_detail,
+ 'server_group_members': self.expected_detail,
+ 'server_groups': self.expected_detail,
+ }
+ }
+ self.assertEqual(expected_response, response)
+
+ def test_detail_v21_user(self):
+ req = fakes.HTTPRequest.blank("?user_id=42")
+ response = self.controller.detail(req, uuids.project_id)
+ expected_response = {
+ 'quota_set': {
+ 'id': uuids.project_id,
+ 'cores': self.expected_detail,
+ 'fixed_ips': self.expected_detail,
+ 'floating_ips': self.expected_detail,
+ 'injected_file_content_bytes': self.expected_detail,
+ 'injected_file_path_bytes': self.expected_detail,
+ 'injected_files': self.expected_detail,
+ 'instances': self.expected_detail,
+ 'key_pairs': self.expected_detail,
+ 'metadata_items': self.expected_detail,
+ 'ram': self.expected_detail,
+ 'security_group_rules': self.expected_detail,
+ 'security_groups': self.expected_detail,
+ 'server_group_members': self.expected_detail,
+ 'server_groups': self.expected_detail,
+ }
+ }
+ self.assertEqual(expected_response, response)
+
+ def test_update_still_rejects_badrequests(self):
+ req = fakes.HTTPRequest.blank("")
+ body = {'quota_set': {'instances': 50, 'cores': 50,
+ 'ram': 51200, 'unsupported': 12}}
+ self.assertRaises(exception.ValidationError, self.controller.update,
+ req, uuids.project_id, body=body)
+
+ @mock.patch.object(objects.Quotas, "create_limit")
+ def test_update_v21(self, mock_create):
+ req = fakes.HTTPRequest.blank("")
+ body = {'quota_set': {'server_groups': 2}}
+ response = self.controller.update(req, uuids.project_id, body=body)
+ expected_response = {
+ 'quota_set': {
+ 'cores': -1,
+ 'fixed_ips': -1,
+ 'floating_ips': -1,
+ 'injected_file_content_bytes': -1,
+ 'injected_file_path_bytes': -1,
+ 'injected_files': -1,
+ 'instances': -1,
+ 'key_pairs': -1,
+ 'metadata_items': -1,
+ 'ram': -1,
+ 'security_group_rules': -1,
+ 'security_groups': -1,
+ 'server_group_members': -1,
+ 'server_groups': -1,
+ }
+ }
+ self.assertEqual(expected_response, response)
+ mock_create.assert_called_once_with(req.environ['nova.context'],
+ uuids.project_id, "server_groups",
+ 2, user_id=None)
+
+ @mock.patch.object(objects.Quotas, "create_limit")
+ def test_update_v21_user(self, mock_create):
+ req = fakes.HTTPRequest.blank("?user_id=42")
+ body = {'quota_set': {'key_pairs': 52}}
+ response = self.controller.update(req, uuids.project_id, body=body)
+ expected_response = {
+ 'quota_set': {
+ 'cores': -1,
+ 'fixed_ips': -1,
+ 'floating_ips': -1,
+ 'injected_file_content_bytes': -1,
+ 'injected_file_path_bytes': -1,
+ 'injected_files': -1,
+ 'instances': -1,
+ 'key_pairs': -1,
+ 'metadata_items': -1,
+ 'ram': -1,
+ 'security_group_rules': -1,
+ 'security_groups': -1,
+ 'server_group_members': -1,
+ 'server_groups': -1,
+ }
+ }
+ self.assertEqual(expected_response, response)
+ mock_create.assert_called_once_with(req.environ['nova.context'],
+ uuids.project_id, "key_pairs", 52,
+ user_id="42")
+
+ def test_defaults_v21(self):
+ req = fakes.HTTPRequest.blank("")
+ response = self.controller.defaults(req, uuids.project_id)
+ expected_response = {
+ 'quota_set': {
+ 'id': uuids.project_id,
+ 'cores': -1,
+ 'fixed_ips': -1,
+ 'floating_ips': -1,
+ 'injected_file_content_bytes': -1,
+ 'injected_file_path_bytes': -1,
+ 'injected_files': -1,
+ 'instances': -1,
+ 'key_pairs': -1,
+ 'metadata_items': -1,
+ 'ram': -1,
+ 'security_group_rules': -1,
+ 'security_groups': -1,
+ 'server_group_members': -1,
+ 'server_groups': -1,
+ }
+ }
+ self.assertEqual(expected_response, response)
+
+ @mock.patch('nova.objects.Quotas.destroy_all_by_project')
+ def test_quotas_delete(self, mock_destroy_all_by_project):
+ req = fakes.HTTPRequest.blank("")
+ self.controller.delete(req, "1234")
+ mock_destroy_all_by_project.assert_called_once_with(
+ req.environ['nova.context'], "1234")
+
+ @mock.patch('nova.objects.Quotas.destroy_all_by_project_and_user')
+ def test_user_quotas_delete(self, mock_destroy_all_by_user):
+ req = fakes.HTTPRequest.blank("?user_id=42")
+ self.controller.delete(req, "1234")
+ mock_destroy_all_by_user.assert_called_once_with(
+ req.environ['nova.context'], "1234", "42")
+
+
+class UnifiedLimitsQuotaSetsTest(NoopQuotaSetsTest):
+ quota_driver = "nova.quota.UnifiedLimitsDriver"
+ # this matches what the db driver returns
+ expected_detail = {'in_use': 0, 'limit': -1, 'reserved': 0}
+
+ def setUp(self):
+ super(UnifiedLimitsQuotaSetsTest, self).setUp()
+ reglimits = {local_limit.SERVER_METADATA_ITEMS: 128,
+ local_limit.INJECTED_FILES: 5,
+ local_limit.INJECTED_FILES_CONTENT: 10 * 1024,
+ local_limit.INJECTED_FILES_PATH: 255,
+ local_limit.KEY_PAIRS: 100,
+ local_limit.SERVER_GROUPS: 12,
+ local_limit.SERVER_GROUP_MEMBERS: 10}
+ self.limit_fixture = self.useFixture(
+ limit_fixture.LimitFixture(reglimits, {}))
+
+ @mock.patch.object(placement_limit, "get_legacy_project_limits")
+ def test_show_v21(self, mock_proj):
+ mock_proj.return_value = {"instances": 1, "cores": 2, "ram": 3}
+ req = fakes.HTTPRequest.blank("")
+ response = self.controller.show(req, uuids.project_id)
+ expected_response = {
+ 'quota_set': {
+ 'id': uuids.project_id,
+ 'cores': 2,
+ 'fixed_ips': -1,
+ 'floating_ips': -1,
+ 'injected_file_content_bytes': 10240,
+ 'injected_file_path_bytes': 255,
+ 'injected_files': 5,
+ 'instances': 1,
+ 'key_pairs': 100,
+ 'metadata_items': 128,
+ 'ram': 3,
+ 'security_group_rules': -1,
+ 'security_groups': -1,
+ 'server_group_members': 10,
+ 'server_groups': 12,
+ }
+ }
+ self.assertEqual(expected_response, response)
+
+ @mock.patch.object(placement_limit, "get_legacy_project_limits")
+ def test_show_v257(self, mock_proj):
+ mock_proj.return_value = {"instances": 1, "cores": 2, "ram": 3}
+ req = fakes.HTTPRequest.blank("", version='2.57')
+ response = self.controller.show(req, uuids.project_id)
+ expected_response = {
+ 'quota_set': {
+ 'id': uuids.project_id,
+ 'cores': 2,
+ 'instances': 1,
+ 'key_pairs': 100,
+ 'metadata_items': 128,
+ 'ram': 3,
+ 'server_group_members': 10,
+ 'server_groups': 12}}
+ self.assertEqual(expected_response, response)
+
+ @mock.patch.object(placement_limit, "get_legacy_counts")
+ @mock.patch.object(placement_limit, "get_legacy_project_limits")
+ @mock.patch.object(objects.InstanceGroupList, "get_counts")
+ def test_detail_v21(self, mock_count, mock_proj, mock_kcount):
+ mock_proj.return_value = {"instances": 1, "cores": 2, "ram": 3}
+ mock_kcount.return_value = {"instances": 4, "cores": 5, "ram": 6}
+ mock_count.return_value = {'project': {'server_groups': 9}}
+ req = fakes.HTTPRequest.blank("")
+ response = self.controller.detail(req, uuids.project_id)
+ expected_response = {
+ 'quota_set': {
+ 'id': uuids.project_id,
+ 'cores': {
+ 'in_use': 5, 'limit': 2, 'reserved': 0},
+ 'fixed_ips': self.expected_detail,
+ 'floating_ips': self.expected_detail,
+ 'injected_file_content_bytes': {
+ 'in_use': 0, 'limit': 10240, 'reserved': 0},
+ 'injected_file_path_bytes': {
+ 'in_use': 0, 'limit': 255, 'reserved': 0},
+ 'injected_files': {
+ 'in_use': 0, 'limit': 5, 'reserved': 0},
+ 'instances': {
+ 'in_use': 4, 'limit': 1, 'reserved': 0},
+ 'key_pairs': {
+ 'in_use': 0, 'limit': 100, 'reserved': 0},
+ 'metadata_items': {
+ 'in_use': 0, 'limit': 128, 'reserved': 0},
+ 'ram': {
+ 'in_use': 6, 'limit': 3, 'reserved': 0},
+ 'security_group_rules': self.expected_detail,
+ 'security_groups': self.expected_detail,
+ 'server_group_members': {
+ 'in_use': 0, 'limit': 10, 'reserved': 0},
+ 'server_groups': {
+ 'in_use': 9, 'limit': 12, 'reserved': 0},
+ }
+ }
+ self.assertEqual(expected_response, response)
+
+ @mock.patch.object(placement_limit, "get_legacy_counts")
+ @mock.patch.object(placement_limit, "get_legacy_project_limits")
+ @mock.patch.object(objects.InstanceGroupList, "get_counts")
+ def test_detail_v21_user(self, mock_count, mock_proj, mock_kcount):
+ mock_proj.return_value = {"instances": 1, "cores": 2, "ram": 3}
+ mock_kcount.return_value = {"instances": 4, "cores": 5, "ram": 6}
+ mock_count.return_value = {'project': {'server_groups': 9}}
+ req = fakes.HTTPRequest.blank("?user_id=42")
+ response = self.controller.detail(req, uuids.project_id)
+ expected_response = {
+ 'quota_set': {
+ 'id': uuids.project_id,
+ 'cores': {
+ 'in_use': 5, 'limit': 2, 'reserved': 0},
+ 'fixed_ips': self.expected_detail,
+ 'floating_ips': self.expected_detail,
+ 'injected_file_content_bytes': {
+ 'in_use': 0, 'limit': 10240, 'reserved': 0},
+ 'injected_file_path_bytes': {
+ 'in_use': 0, 'limit': 255, 'reserved': 0},
+ 'injected_files': {
+ 'in_use': 0, 'limit': 5, 'reserved': 0},
+ 'instances': {
+ 'in_use': 4, 'limit': 1, 'reserved': 0},
+ 'key_pairs': {
+ 'in_use': 0, 'limit': 100, 'reserved': 0},
+ 'metadata_items': {
+ 'in_use': 0, 'limit': 128, 'reserved': 0},
+ 'ram': {
+ 'in_use': 6, 'limit': 3, 'reserved': 0},
+ 'security_group_rules': self.expected_detail,
+ 'security_groups': self.expected_detail,
+ 'server_group_members': {
+ 'in_use': 0, 'limit': 10, 'reserved': 0},
+ 'server_groups': {
+ 'in_use': 9, 'limit': 12, 'reserved': 0},
+ }
+ }
+ self.assertEqual(expected_response, response)
+
+ @mock.patch.object(placement_limit, "get_legacy_project_limits")
+ @mock.patch.object(objects.Quotas, "create_limit")
+ def test_update_v21(self, mock_create, mock_proj):
+ mock_proj.return_value = {"instances": 1, "cores": 2, "ram": 3}
+ req = fakes.HTTPRequest.blank("")
+ # TODO(johngarbutt) still need to implement get_settable_quotas
+ body = {'quota_set': {'server_groups': 2}}
+ response = self.controller.update(req, uuids.project_id, body=body)
+ expected_response = {
+ 'quota_set': {
+ 'cores': 2,
+ 'fixed_ips': -1,
+ 'floating_ips': -1,
+ 'injected_file_content_bytes': 10240,
+ 'injected_file_path_bytes': 255,
+ 'injected_files': 5,
+ 'instances': 1,
+ 'key_pairs': 100,
+ 'metadata_items': 128,
+ 'ram': 3,
+ 'security_group_rules': -1,
+ 'security_groups': -1,
+ 'server_group_members': 10,
+ 'server_groups': 12,
+ }
+ }
+ self.assertEqual(expected_response, response)
+ self.assertEqual(0, mock_create.call_count)
+
+ @mock.patch.object(placement_limit, "get_legacy_project_limits")
+ @mock.patch.object(objects.Quotas, "create_limit")
+ def test_update_v21_user(self, mock_create, mock_proj):
+ mock_proj.return_value = {"instances": 1, "cores": 2, "ram": 3}
+ req = fakes.HTTPRequest.blank("?user_id=42")
+ body = {'quota_set': {'key_pairs': 52}}
+ response = self.controller.update(req, uuids.project_id, body=body)
+ expected_response = {
+ 'quota_set': {
+ 'cores': 2,
+ 'fixed_ips': -1,
+ 'floating_ips': -1,
+ 'injected_file_content_bytes': 10240,
+ 'injected_file_path_bytes': 255,
+ 'injected_files': 5,
+ 'instances': 1,
+ 'key_pairs': 100,
+ 'metadata_items': 128,
+ 'ram': 3,
+ 'security_group_rules': -1,
+ 'security_groups': -1,
+ 'server_group_members': 10,
+ 'server_groups': 12,
+ }
+ }
+ self.assertEqual(expected_response, response)
+ self.assertEqual(0, mock_create.call_count)
+
+ @mock.patch.object(placement_limit, "get_legacy_default_limits")
+ def test_defaults_v21(self, mock_default):
+ mock_default.return_value = {"instances": 1, "cores": 2, "ram": 3}
+ req = fakes.HTTPRequest.blank("")
+ response = self.controller.defaults(req, uuids.project_id)
+ expected_response = {
+ 'quota_set': {
+ 'id': uuids.project_id,
+ 'cores': 2,
+ 'fixed_ips': -1,
+ 'floating_ips': -1,
+ 'injected_file_content_bytes': 10240,
+ 'injected_file_path_bytes': 255,
+ 'injected_files': 5,
+ 'instances': 1,
+ 'key_pairs': 100,
+ 'metadata_items': 128,
+ 'ram': 3,
+ 'security_group_rules': -1,
+ 'security_groups': -1,
+ 'server_group_members': 10,
+ 'server_groups': 12,
+ }
+ }
+ self.assertEqual(expected_response, response)
+
+ def test_defaults_v21_different_limit_values(self):
+ reglimits = {local_limit.SERVER_METADATA_ITEMS: 7,
+ local_limit.INJECTED_FILES: 6,
+ local_limit.INJECTED_FILES_CONTENT: 4,
+ local_limit.INJECTED_FILES_PATH: 5,
+ local_limit.KEY_PAIRS: 1,
+ local_limit.SERVER_GROUPS: 3,
+ local_limit.SERVER_GROUP_MEMBERS: 2}
+ self.limit_fixture.reglimits = reglimits
+
+ req = fakes.HTTPRequest.blank("")
+ response = self.controller.defaults(req, uuids.project_id)
+ expected_response = {
+ 'quota_set': {
+ 'id': uuids.project_id,
+ 'cores': 0,
+ 'fixed_ips': -1,
+ 'floating_ips': -1,
+ 'injected_file_content_bytes': 4,
+ 'injected_file_path_bytes': 5,
+ 'injected_files': 6,
+ 'instances': 0,
+ 'key_pairs': 1,
+ 'metadata_items': 7,
+ 'ram': 0,
+ 'security_group_rules': -1,
+ 'security_groups': -1,
+ 'server_group_members': 2,
+ 'server_groups': 3,
+ }
+ }
+ self.assertEqual(expected_response, response)
+
+ @mock.patch('nova.objects.Quotas.destroy_all_by_project')
+ def test_quotas_delete(self, mock_destroy_all_by_project):
+ req = fakes.HTTPRequest.blank("")
+ self.controller.delete(req, "1234")
+ # Ensure destroy isn't called for unified limits
+ self.assertEqual(0, mock_destroy_all_by_project.call_count)
+
+ @mock.patch('nova.objects.Quotas.destroy_all_by_project_and_user')
+ def test_user_quotas_delete(self, mock_destroy_all_by_user):
+ req = fakes.HTTPRequest.blank("?user_id=42")
+ self.controller.delete(req, "1234")
+ # Ensure destroy isn't called for unified limits
+ self.assertEqual(0, mock_destroy_all_by_user.call_count)
diff --git a/nova/tests/unit/api/openstack/compute/test_remote_consoles.py b/nova/tests/unit/api/openstack/compute/test_remote_consoles.py
index 6427b1abf0..961f4a02c9 100644
--- a/nova/tests/unit/api/openstack/compute/test_remote_consoles.py
+++ b/nova/tests/unit/api/openstack/compute/test_remote_consoles.py
@@ -13,7 +13,8 @@
# License for the specific language governing permissions and limitations
# under the License.
-import mock
+from unittest import mock
+
import webob
from nova.api.openstack import api_version_request
@@ -103,6 +104,18 @@ class ConsolesExtensionTestV21(test.NoDBTestCase):
'get_vnc_console',
exception.InstanceNotFound(instance_id=fakes.FAKE_UUID))
+ def test_get_vnc_console_instance_invalid_state(self):
+ body = {'os-getVNCConsole': {'type': 'novnc'}}
+ self._check_console_failure(
+ self.controller.get_vnc_console,
+ webob.exc.HTTPConflict,
+ body,
+ 'get_vnc_console',
+ exception.InstanceInvalidState(
+ attr='fake-attr', state='fake-state', method='fake-method',
+ instance_uuid=fakes.FAKE_UUID)
+ )
+
def test_get_vnc_console_invalid_type(self):
body = {'os-getVNCConsole': {'type': 'invalid'}}
self._check_console_failure(
@@ -446,7 +459,7 @@ class ConsolesExtensionTestV26(test.NoDBTestCase):
self.req, fakes.FAKE_UUID, body=body)
self.assertTrue(mock_handler.called)
- def test_create_console_not_found(self,):
+ def test_create_console_not_found(self):
mock_handler = mock.MagicMock()
mock_handler.side_effect = exception.InstanceNotFound(
instance_id='xxx')
diff --git a/nova/tests/unit/api/openstack/compute/test_rescue.py b/nova/tests/unit/api/openstack/compute/test_rescue.py
index 28b8217d1a..8a87f52222 100644
--- a/nova/tests/unit/api/openstack/compute/test_rescue.py
+++ b/nova/tests/unit/api/openstack/compute/test_rescue.py
@@ -12,7 +12,7 @@
# License for the specific language governing permissions and limitations
# under the License.
-import mock
+from unittest import mock
import ddt
from oslo_utils.fixture import uuidsentinel as uuids
diff --git a/nova/tests/unit/api/openstack/compute/test_security_groups.py b/nova/tests/unit/api/openstack/compute/test_security_groups.py
index 71cdcbc871..4a85a9997d 100644
--- a/nova/tests/unit/api/openstack/compute/test_security_groups.py
+++ b/nova/tests/unit/api/openstack/compute/test_security_groups.py
@@ -13,8 +13,9 @@
# License for the specific language governing permissions and limitations
# under the License.
-import mock
from neutronclient.common import exceptions as n_exc
+from unittest import mock
+
from oslo_config import cfg
from oslo_serialization import jsonutils
from oslo_utils import encodeutils
diff --git a/nova/tests/unit/api/openstack/compute/test_server_actions.py b/nova/tests/unit/api/openstack/compute/test_server_actions.py
index d07924abe8..08f7a31573 100644
--- a/nova/tests/unit/api/openstack/compute/test_server_actions.py
+++ b/nova/tests/unit/api/openstack/compute/test_server_actions.py
@@ -13,9 +13,10 @@
# License for the specific language governing permissions and limitations
# under the License.
+from unittest import mock
+
import ddt
import fixtures
-import mock
from oslo_utils.fixture import uuidsentinel as uuids
from oslo_utils import uuidutils
import webob
@@ -66,11 +67,11 @@ class ServerActionsControllerTestV21(test.TestCase):
self.controller = self._get_controller()
self.compute_api = self.controller.compute_api
- # We don't care about anything getting as far as hitting the compute
- # RPC API so we just mock it out here.
- mock_rpcapi = mock.patch.object(self.compute_api, 'compute_rpcapi')
- mock_rpcapi.start()
- self.addCleanup(mock_rpcapi.stop)
+ # In most of the cases we don't care about anything getting as far as
+ # hitting the compute RPC API so we just mock it out here.
+ patcher_rpcapi = mock.patch.object(self.compute_api, 'compute_rpcapi')
+ self.mock_rpcapi = patcher_rpcapi.start()
+ self.addCleanup(patcher_rpcapi.stop)
# The project_id here matches what is used by default in
# fake_compute_get which need to match for policy checks.
self.req = fakes.HTTPRequest.blank('',
@@ -1079,21 +1080,23 @@ class ServerActionsControllerTestV21(test.TestCase):
snapshot = dict(id=_fake_id('d'))
+ self.mock_rpcapi.quiesce_instance.side_effect = (
+ exception.InstanceQuiesceNotSupported(
+ instance_id="fake", reason="test"
+ )
+ )
+
with test.nested(
mock.patch.object(
self.controller.compute_api.volume_api, 'get_absolute_limits',
return_value={'totalSnapshotsUsed': 0,
'maxTotalSnapshots': 10}),
- mock.patch.object(self.controller.compute_api.compute_rpcapi,
- 'quiesce_instance',
- side_effect=exception.InstanceQuiesceNotSupported(
- instance_id='fake', reason='test')),
mock.patch.object(self.controller.compute_api.volume_api, 'get',
return_value=volume),
mock.patch.object(self.controller.compute_api.volume_api,
'create_snapshot_force',
return_value=snapshot),
- ) as (mock_get_limits, mock_quiesce, mock_vol_get, mock_vol_create):
+ ) as (mock_get_limits, mock_vol_get, mock_vol_create):
if mock_vol_create_side_effect:
mock_vol_create.side_effect = mock_vol_create_side_effect
@@ -1125,7 +1128,7 @@ class ServerActionsControllerTestV21(test.TestCase):
for k in extra_properties.keys():
self.assertEqual(properties[k], extra_properties[k])
- mock_quiesce.assert_called_once_with(mock.ANY, mock.ANY)
+ self.mock_rpcapi.quiesce_instance.assert_called_once()
mock_vol_get.assert_called_once_with(mock.ANY, volume['id'])
mock_vol_create.assert_called_once_with(mock.ANY, volume['id'],
mock.ANY, mock.ANY)
@@ -1189,21 +1192,23 @@ class ServerActionsControllerTestV21(test.TestCase):
snapshot = dict(id=_fake_id('d'))
+ self.mock_rpcapi.quiesce_instance.side_effect = (
+ exception.InstanceQuiesceNotSupported(
+ instance_id="fake", reason="test"
+ )
+ )
+
with test.nested(
mock.patch.object(
self.controller.compute_api.volume_api, 'get_absolute_limits',
return_value={'totalSnapshotsUsed': 0,
'maxTotalSnapshots': 10}),
- mock.patch.object(self.controller.compute_api.compute_rpcapi,
- 'quiesce_instance',
- side_effect=exception.InstanceQuiesceNotSupported(
- instance_id='fake', reason='test')),
mock.patch.object(self.controller.compute_api.volume_api, 'get',
return_value=volume),
mock.patch.object(self.controller.compute_api.volume_api,
'create_snapshot_force',
return_value=snapshot),
- ) as (mock_get_limits, mock_quiesce, mock_vol_get, mock_vol_create):
+ ) as (mock_get_limits, mock_vol_get, mock_vol_create):
response = self.controller._action_create_image(self.req,
FAKE_UUID, body=body)
@@ -1218,7 +1223,7 @@ class ServerActionsControllerTestV21(test.TestCase):
for key, val in extra_metadata.items():
self.assertEqual(properties[key], val)
- mock_quiesce.assert_called_once_with(mock.ANY, mock.ANY)
+ self.mock_rpcapi.quiesce_instance.assert_called_once()
mock_vol_get.assert_called_once_with(mock.ANY, volume['id'])
mock_vol_create.assert_called_once_with(mock.ANY, volume['id'],
mock.ANY, mock.ANY)
diff --git a/nova/tests/unit/api/openstack/compute/test_server_diagnostics.py b/nova/tests/unit/api/openstack/compute/test_server_diagnostics.py
index d215f3e903..12d8bbb318 100644
--- a/nova/tests/unit/api/openstack/compute/test_server_diagnostics.py
+++ b/nova/tests/unit/api/openstack/compute/test_server_diagnostics.py
@@ -13,7 +13,8 @@
# License for the specific language governing permissions and limitations
# under the License.
-import mock
+from unittest import mock
+
from oslo_serialization import jsonutils
from oslo_utils.fixture import uuidsentinel as uuids
diff --git a/nova/tests/unit/api/openstack/compute/test_server_external_events.py b/nova/tests/unit/api/openstack/compute/test_server_external_events.py
index 2ca97fc6d8..e366d0acdd 100644
--- a/nova/tests/unit/api/openstack/compute/test_server_external_events.py
+++ b/nova/tests/unit/api/openstack/compute/test_server_external_events.py
@@ -12,8 +12,9 @@
# License for the specific language governing permissions and limitations
# under the License.
+from unittest import mock
+
import fixtures as fx
-import mock
from oslo_utils.fixture import uuidsentinel as uuids
from nova.api.openstack.compute import server_external_events \
@@ -192,7 +193,7 @@ class ServerExternalEventsTestV21(test.NoDBTestCase):
self.api.create, self.req, body=body)
def test_create_unknown_events(self):
- self.event_1['name'] = 'unkown_event'
+ self.event_1['name'] = 'unknown_event'
body = {'events': self.event_1}
self.assertRaises(self.invalid_error,
self.api.create, self.req, body=body)
diff --git a/nova/tests/unit/api/openstack/compute/test_server_group_quotas.py b/nova/tests/unit/api/openstack/compute/test_server_group_quotas.py
index 6b08be6fd9..fe7a60f956 100644
--- a/nova/tests/unit/api/openstack/compute/test_server_group_quotas.py
+++ b/nova/tests/unit/api/openstack/compute/test_server_group_quotas.py
@@ -13,14 +13,18 @@
# License for the specific language governing permissions and limitations
# under the License.
-import mock
+from unittest import mock
+
from oslo_config import cfg
+from oslo_limit import fixture as limit_fixture
from oslo_utils.fixture import uuidsentinel as uuids
from oslo_utils import uuidutils
import webob
from nova.api.openstack.compute import server_groups as sg_v21
from nova import context
+from nova import exception
+from nova.limit import local as local_limit
from nova import objects
from nova import test
from nova.tests.unit.api.openstack import fakes
@@ -116,14 +120,41 @@ class ServerGroupQuotasTestV21(test.TestCase):
self.controller.create,
self.req, body={'server_group': sgroup})
+ def _test_create_server_group_during_recheck(self, mock_method):
+ self._setup_quotas()
+ sgroup = server_group_template()
+ policies = ['anti-affinity']
+ sgroup['policies'] = policies
+ e = self.assertRaises(webob.exc.HTTPForbidden,
+ self.controller.create,
+ self.req, body={'server_group': sgroup})
+ self.assertEqual(2, mock_method.call_count)
+ return e
+
@mock.patch('nova.objects.Quotas.check_deltas')
- def test_create_server_group_recheck_disabled(self, mock_check):
+ def test_create_server_group_during_recheck(self, mock_check):
+ """Simulate a race where this request initially has enough quota to
+ progress partially through the create path but then fails the quota
+ recheck because a parallel request filled up the quota first.
+ """
+ # First quota check succeeds, second (recheck) fails.
+ mock_check.side_effect = [None,
+ exception.OverQuota(overs='server_groups')]
+ e = self._test_create_server_group_during_recheck(mock_check)
+ expected = 'Quota exceeded, too many server groups.'
+ self.assertEqual(expected, str(e))
+
+ def _test_create_server_group_recheck_disabled(self):
self.flags(recheck_quota=False, group='quota')
self._setup_quotas()
sgroup = server_group_template()
policies = ['anti-affinity']
sgroup['policies'] = policies
self.controller.create(self.req, body={'server_group': sgroup})
+
+ @mock.patch('nova.objects.Quotas.check_deltas')
+ def test_create_server_group_recheck_disabled(self, mock_check):
+ self._test_create_server_group_recheck_disabled()
ctxt = self.req.environ['nova.context']
mock_check.assert_called_once_with(ctxt, {'server_groups': 1},
ctxt.project_id, ctxt.user_id)
@@ -170,3 +201,76 @@ class ServerGroupQuotasTestV21(test.TestCase):
else:
status_int = resp.status_int
self.assertEqual(204, status_int)
+
+
+class ServerGroupQuotasUnifiedLimitsTestV21(ServerGroupQuotasTestV21):
+
+ def setUp(self):
+ super(ServerGroupQuotasUnifiedLimitsTestV21, self).setUp()
+ self.flags(driver='nova.quota.UnifiedLimitsDriver', group='quota')
+ self.req = fakes.HTTPRequest.blank('')
+ self.controller = sg_v21.ServerGroupController()
+ self.limit_fixture = self.useFixture(
+ limit_fixture.LimitFixture({'server_groups': 10}, {}))
+
+ @mock.patch('nova.limit.local.enforce_db_limit')
+ def test_create_server_group_during_recheck(self, mock_enforce):
+ """Simulate a race where this request initially has enough quota to
+ progress partially through the create path but then fails the quota
+ recheck because a parallel request filled up the quota first.
+ """
+ # First quota check succeeds, second (recheck) fails.
+ mock_enforce.side_effect = [
+ None,
+ exception.ServerGroupLimitExceeded(message='oslo.limit message')]
+ # Run the test using the unified limits enforce method.
+ e = self._test_create_server_group_during_recheck(mock_enforce)
+ expected = 'oslo.limit message'
+ self.assertEqual(expected, str(e))
+
+ @mock.patch('nova.limit.local.enforce_db_limit')
+ def test_create_server_group_recheck_disabled(self, mock_enforce):
+ # Run the test using the unified limits enforce method.
+ self._test_create_server_group_recheck_disabled()
+ ctxt = self.req.environ['nova.context']
+ mock_enforce.assert_called_once_with(ctxt, 'server_groups',
+ entity_scope=ctxt.project_id,
+ delta=1)
+
+ def test_create_group_fails_with_zero_quota(self):
+ self.limit_fixture.reglimits = {'server_groups': 0}
+ sgroup = {'name': 'test', 'policies': ['anti-affinity']}
+ exc = self.assertRaises(webob.exc.HTTPForbidden,
+ self.controller.create,
+ self.req, body={'server_group': sgroup})
+ msg = ("Resource %s is over limit" % local_limit.SERVER_GROUPS)
+ self.assertIn(msg, str(exc))
+
+ def test_create_only_one_group_when_limit_is_one(self):
+ self.limit_fixture.reglimits = {'server_groups': 1}
+ policies = ['anti-affinity']
+ sgroup = {'name': 'test', 'policies': policies}
+ res_dict = self.controller.create(
+ self.req, body={'server_group': sgroup})
+ self.assertEqual(res_dict['server_group']['name'], 'test')
+ self.assertTrue(uuidutils.is_uuid_like(res_dict['server_group']['id']))
+ self.assertEqual(res_dict['server_group']['policies'], policies)
+
+ # prove we can't create two, as limited to one
+ sgroup2 = {'name': 'test2', 'policies': policies}
+ exc = self.assertRaises(webob.exc.HTTPForbidden,
+ self.controller.create,
+ self.req, body={'server_group': sgroup2})
+ msg = ("Resource %s is over limit" % local_limit.SERVER_GROUPS)
+ self.assertIn(msg, str(exc))
+
+ # delete first one
+ self.controller.delete(self.req, res_dict['server_group']['id'])
+
+ # prove we can now create the second one
+ res_dict2 = self.controller.create(
+ self.req, body={'server_group': sgroup2})
+ self.assertEqual(res_dict2['server_group']['name'], 'test2')
+ self.assertTrue(
+ uuidutils.is_uuid_like(res_dict2['server_group']['id']))
+ self.assertEqual(res_dict2['server_group']['policies'], policies)
diff --git a/nova/tests/unit/api/openstack/compute/test_server_groups.py b/nova/tests/unit/api/openstack/compute/test_server_groups.py
index a0d1712343..9d99c3ae6d 100644
--- a/nova/tests/unit/api/openstack/compute/test_server_groups.py
+++ b/nova/tests/unit/api/openstack/compute/test_server_groups.py
@@ -14,7 +14,8 @@
# under the License.
import copy
-import mock
+from unittest import mock
+
from oslo_utils.fixture import uuidsentinel
from oslo_utils import uuidutils
import webob
@@ -86,7 +87,8 @@ class ServerGroupTestV21(test.NoDBTestCase):
def setUp(self):
super(ServerGroupTestV21, self).setUp()
self._setup_controller()
- self.req = fakes.HTTPRequest.blank('')
+ self.member_req = fakes.HTTPRequest.member_req('')
+ self.reader_req = fakes.HTTPRequest.reader_req('')
self.admin_req = fakes.HTTPRequest.blank('', use_admin_context=True)
self.foo_req = fakes.HTTPRequest.blank('', project_id='foo')
self.policy = self.useFixture(fixtures.RealPolicyFixture())
@@ -113,20 +115,20 @@ class ServerGroupTestV21(test.NoDBTestCase):
def test_create_server_group_with_no_policies(self):
sgroup = server_group_template()
self.assertRaises(self.validation_error, self.controller.create,
- self.req, body={'server_group': sgroup})
+ self.member_req, body={'server_group': sgroup})
def _create_server_group_normal(self, policies=None, policy=None,
rules=None):
sgroup = server_group_template()
sgroup['policies'] = policies
- res_dict = self.controller.create(self.req,
+ res_dict = self.controller.create(self.member_req,
body={'server_group': sgroup})
self.assertEqual(res_dict['server_group']['name'], 'test')
self.assertTrue(uuidutils.is_uuid_like(res_dict['server_group']['id']))
self.assertEqual(res_dict['server_group']['policies'], policies)
def test_create_server_group_with_new_policy_before_264(self):
- req = fakes.HTTPRequest.blank('', version='2.63')
+ req = fakes.HTTPRequest.member_req('', version='2.63')
policy = 'anti-affinity'
rules = {'max_server_per_host': 3}
# 'policy' isn't an acceptable request key before 2.64
@@ -161,7 +163,7 @@ class ServerGroupTestV21(test.NoDBTestCase):
self.controller.create(self.admin_req, body={'server_group': sgroup})
# test as non-admin
- self.controller.create(self.req, body={'server_group': sgroup})
+ self.controller.create(self.member_req, body={'server_group': sgroup})
def _create_instance(self, ctx, cell):
with context.target_cell(ctx, cell) as cctx:
@@ -288,7 +290,7 @@ class ServerGroupTestV21(test.NoDBTestCase):
path = path or '/os-server-groups?all_projects=True'
if limited:
path += limited
- req = fakes.HTTPRequest.blank(path, version=api_version)
+ reader_req = fakes.HTTPRequest.reader_req(path, version=api_version)
admin_req = fakes.HTTPRequest.blank(path, use_admin_context=True,
version=api_version)
@@ -297,7 +299,7 @@ class ServerGroupTestV21(test.NoDBTestCase):
self.assertEqual(all, res_dict)
# test as non-admin
- res_dict = self.controller.index(req)
+ res_dict = self.controller.index(reader_req)
self.assertEqual(tenant_specific, res_dict)
@mock.patch('nova.objects.InstanceGroupList.get_by_project_id')
@@ -346,25 +348,27 @@ class ServerGroupTestV21(test.NoDBTestCase):
return_get_by_project = return_server_groups()
mock_get_by_project.return_value = return_get_by_project
path = '/os-server-groups'
- req = fakes.HTTPRequest.blank(path, version=api_version)
+ req = fakes.HTTPRequest.reader_req(path, version=api_version)
res_dict = self.controller.index(req)
self.assertEqual(expected, res_dict)
def test_display_members(self):
ctx = context.RequestContext('fake_user', fakes.FAKE_PROJECT_ID)
(ig_uuid, instances, members) = self._create_groups_and_instances(ctx)
- res_dict = self.controller.show(self.req, ig_uuid)
+ res_dict = self.controller.show(self.reader_req, ig_uuid)
result_members = res_dict['server_group']['members']
self.assertEqual(3, len(result_members))
for member in members:
self.assertIn(member, result_members)
def test_display_members_with_nonexistent_group(self):
- self.assertRaises(webob.exc.HTTPNotFound,
- self.controller.show, self.req, uuidsentinel.group)
+ self.assertRaises(
+ webob.exc.HTTPNotFound,
+ self.controller.show, self.reader_req, uuidsentinel.group)
def test_display_active_members_only(self):
- ctx = context.RequestContext('fake_user', fakes.FAKE_PROJECT_ID)
+ ctx = context.RequestContext('fake_user', fakes.FAKE_PROJECT_ID,
+ roles=['member', 'reader'])
(ig_uuid, instances, members) = self._create_groups_and_instances(ctx)
# delete an instance
@@ -378,7 +382,7 @@ class ServerGroupTestV21(test.NoDBTestCase):
self.assertRaises(exception.InstanceNotFound,
objects.Instance.get_by_uuid,
ctx, instances[1].uuid)
- res_dict = self.controller.show(self.req, ig_uuid)
+ res_dict = self.controller.show(self.reader_req, ig_uuid)
result_members = res_dict['server_group']['members']
# check that only the active instance is displayed
self.assertEqual(2, len(result_members))
@@ -392,7 +396,7 @@ class ServerGroupTestV21(test.NoDBTestCase):
self.controller.show(self.admin_req, ig_uuid)
# test as non-admin, same project
- self.controller.show(self.req, ig_uuid)
+ self.controller.show(self.reader_req, ig_uuid)
# test as non-admin, different project
self.assertRaises(webob.exc.HTTPNotFound,
@@ -405,7 +409,7 @@ class ServerGroupTestV21(test.NoDBTestCase):
sgroup = server_group_template(name='good* $%name',
policies=['affinity'])
- res_dict = self.controller.create(self.req,
+ res_dict = self.controller.create(self.member_req,
body={'server_group': sgroup})
self.assertEqual(res_dict['server_group']['name'], 'good* $%name')
@@ -413,99 +417,99 @@ class ServerGroupTestV21(test.NoDBTestCase):
# blank name
sgroup = server_group_template(name='', policies=['test_policy'])
self.assertRaises(self.validation_error, self.controller.create,
- self.req, body={'server_group': sgroup})
+ self.member_req, body={'server_group': sgroup})
# name with length 256
sgroup = server_group_template(name='1234567890' * 26,
policies=['test_policy'])
self.assertRaises(self.validation_error, self.controller.create,
- self.req, body={'server_group': sgroup})
+ self.member_req, body={'server_group': sgroup})
# non-string name
sgroup = server_group_template(name=12, policies=['test_policy'])
self.assertRaises(self.validation_error, self.controller.create,
- self.req, body={'server_group': sgroup})
+ self.member_req, body={'server_group': sgroup})
# name with leading spaces
sgroup = server_group_template(name=' leading spaces',
policies=['test_policy'])
self.assertRaises(self.validation_error, self.controller.create,
- self.req, body={'server_group': sgroup})
+ self.member_req, body={'server_group': sgroup})
# name with trailing spaces
sgroup = server_group_template(name='trailing space ',
policies=['test_policy'])
self.assertRaises(self.validation_error, self.controller.create,
- self.req, body={'server_group': sgroup})
+ self.member_req, body={'server_group': sgroup})
# name with all spaces
sgroup = server_group_template(name=' ',
policies=['test_policy'])
self.assertRaises(self.validation_error, self.controller.create,
- self.req, body={'server_group': sgroup})
+ self.member_req, body={'server_group': sgroup})
# name with unprintable character
sgroup = server_group_template(name='bad\x00name',
policies=['test_policy'])
self.assertRaises(self.validation_error, self.controller.create,
- self.req, body={'server_group': sgroup})
+ self.member_req, body={'server_group': sgroup})
# name with out of range char U0001F4A9
sgroup = server_group_template(name=u"\U0001F4A9",
policies=['affinity'])
self.assertRaises(self.validation_error, self.controller.create,
- self.req, body={'server_group': sgroup})
+ self.member_req, body={'server_group': sgroup})
def test_create_server_group_with_illegal_policies(self):
# blank policy
sgroup = server_group_template(name='fake-name', policies='')
self.assertRaises(self.validation_error, self.controller.create,
- self.req, body={'server_group': sgroup})
+ self.member_req, body={'server_group': sgroup})
# policy as integer
sgroup = server_group_template(name='fake-name', policies=7)
self.assertRaises(self.validation_error, self.controller.create,
- self.req, body={'server_group': sgroup})
+ self.member_req, body={'server_group': sgroup})
# policy as string
sgroup = server_group_template(name='fake-name', policies='invalid')
self.assertRaises(self.validation_error, self.controller.create,
- self.req, body={'server_group': sgroup})
+ self.member_req, body={'server_group': sgroup})
# policy as None
sgroup = server_group_template(name='fake-name', policies=None)
self.assertRaises(self.validation_error, self.controller.create,
- self.req, body={'server_group': sgroup})
+ self.member_req, body={'server_group': sgroup})
def test_create_server_group_conflicting_policies(self):
sgroup = server_group_template()
policies = ['anti-affinity', 'affinity']
sgroup['policies'] = policies
self.assertRaises(self.validation_error, self.controller.create,
- self.req, body={'server_group': sgroup})
+ self.member_req, body={'server_group': sgroup})
def test_create_server_group_with_duplicate_policies(self):
sgroup = server_group_template()
policies = ['affinity', 'affinity']
sgroup['policies'] = policies
self.assertRaises(self.validation_error, self.controller.create,
- self.req, body={'server_group': sgroup})
+ self.member_req, body={'server_group': sgroup})
def test_create_server_group_not_supported(self):
sgroup = server_group_template()
policies = ['storage-affinity', 'anti-affinity', 'rack-affinity']
sgroup['policies'] = policies
self.assertRaises(self.validation_error, self.controller.create,
- self.req, body={'server_group': sgroup})
+ self.member_req, body={'server_group': sgroup})
def test_create_server_group_with_no_body(self):
self.assertRaises(self.validation_error,
- self.controller.create, self.req, body=None)
+ self.controller.create, self.member_req, body=None)
def test_create_server_group_with_no_server_group(self):
body = {'no-instanceGroup': None}
self.assertRaises(self.validation_error,
- self.controller.create, self.req, body=body)
+ self.controller.create, self.member_req, body=body)
def test_list_server_group_by_tenant(self):
self._test_list_server_group_by_tenant(
@@ -527,7 +531,7 @@ class ServerGroupTestV21(test.NoDBTestCase):
self.controller.index(self.admin_req)
# test as non-admin
- self.controller.index(self.req)
+ self.controller.index(self.reader_req)
def test_list_server_group_multiple_param(self):
self._test_list_server_group(api_version=self.wsgi_api_version,
@@ -597,7 +601,7 @@ class ServerGroupTestV21(test.NoDBTestCase):
self.stub_out('nova.objects.InstanceGroup.get_by_uuid',
return_server_group)
- resp = self.controller.delete(self.req, uuidsentinel.sg1_id)
+ resp = self.controller.delete(self.member_req, uuidsentinel.sg1_id)
mock_destroy.assert_called_once_with()
# NOTE: on v2.1, http status code is set as wsgi_code of API
@@ -610,7 +614,7 @@ class ServerGroupTestV21(test.NoDBTestCase):
def test_delete_non_existing_server_group(self):
self.assertRaises(webob.exc.HTTPNotFound, self.controller.delete,
- self.req, 'invalid')
+ self.member_req, 'invalid')
def test_delete_server_group_rbac_default(self):
ctx = context.RequestContext('fake_user', fakes.FAKE_PROJECT_ID)
@@ -621,7 +625,7 @@ class ServerGroupTestV21(test.NoDBTestCase):
# test as non-admin
ig_uuid = self._create_groups_and_instances(ctx)[0]
- self.controller.delete(self.req, ig_uuid)
+ self.controller.delete(self.member_req, ig_uuid)
class ServerGroupTestV213(ServerGroupTestV21):
@@ -648,7 +652,7 @@ class ServerGroupTestV264(ServerGroupTestV213):
def _create_server_group_normal(self, policies=None, policy=None,
rules=None):
- req = fakes.HTTPRequest.blank('', version=self.wsgi_api_version)
+ req = fakes.HTTPRequest.member_req('', version=self.wsgi_api_version)
sgroup = server_group_template()
sgroup['rules'] = rules or {}
sgroup['policy'] = policy
@@ -673,7 +677,7 @@ class ServerGroupTestV264(ServerGroupTestV213):
self.assertEqual(res_dict['server_group']['rules'], {})
def _display_server_group(self, uuid):
- req = fakes.HTTPRequest.blank('', version=self.wsgi_api_version)
+ req = fakes.HTTPRequest.reader_req('', version=self.wsgi_api_version)
group = self.controller.show(req, uuid)
return group
@@ -689,7 +693,7 @@ class ServerGroupTestV264(ServerGroupTestV213):
self.assertEqual(res_dict['server_group']['rules'], rules)
def test_create_affinity_server_group_with_invalid_policy(self):
- req = fakes.HTTPRequest.blank('', version=self.wsgi_api_version)
+ req = fakes.HTTPRequest.member_req('', version=self.wsgi_api_version)
sgroup = server_group_template(policy='affinity',
rules={'max_server_per_host': 3})
result = self.assertRaises(webob.exc.HTTPBadRequest,
@@ -697,7 +701,7 @@ class ServerGroupTestV264(ServerGroupTestV213):
self.assertIn("Only anti-affinity policy supports rules", str(result))
def test_create_anti_affinity_server_group_with_invalid_rules(self):
- req = fakes.HTTPRequest.blank('', version=self.wsgi_api_version)
+ req = fakes.HTTPRequest.member_req('', version=self.wsgi_api_version)
# A negative test for key is unknown, the value is not positive
# and not integer
invalid_rules = [{'unknown_key': '3'},
@@ -717,7 +721,7 @@ class ServerGroupTestV264(ServerGroupTestV213):
return_value=32)
def test_create_server_group_with_low_version_compute_service(self,
mock_get_v):
- req = fakes.HTTPRequest.blank('', version=self.wsgi_api_version)
+ req = fakes.HTTPRequest.member_req('', version=self.wsgi_api_version)
sgroup = server_group_template(policy='anti-affinity',
rules={'max_server_per_host': 3})
result = self.assertRaises(
@@ -733,7 +737,7 @@ class ServerGroupTestV264(ServerGroupTestV213):
self._create_server_group_normal(policy=policy)
def test_policies_since_264(self):
- req = fakes.HTTPRequest.blank('', version=self.wsgi_api_version)
+ req = fakes.HTTPRequest.member_req('', version=self.wsgi_api_version)
# 'policies' isn't allowed in request >= 2.64
sgroup = server_group_template(policies=['anti-affinity'])
self.assertRaises(
@@ -741,14 +745,14 @@ class ServerGroupTestV264(ServerGroupTestV213):
req, body={'server_group': sgroup})
def test_create_server_group_without_policy(self):
- req = fakes.HTTPRequest.blank('', version=self.wsgi_api_version)
+ req = fakes.HTTPRequest.member_req('', version=self.wsgi_api_version)
# 'policy' is required request key in request >= 2.64
sgroup = server_group_template()
self.assertRaises(self.validation_error, self.controller.create,
req, body={'server_group': sgroup})
def test_create_server_group_with_illegal_policies(self):
- req = fakes.HTTPRequest.blank('', version=self.wsgi_api_version)
+ req = fakes.HTTPRequest.member_req('', version=self.wsgi_api_version)
# blank policy
sgroup = server_group_template(policy='')
self.assertRaises(self.validation_error, self.controller.create,
@@ -770,7 +774,7 @@ class ServerGroupTestV264(ServerGroupTestV213):
req, body={'server_group': sgroup})
def test_additional_params(self):
- req = fakes.HTTPRequest.blank('', version=self.wsgi_api_version)
+ req = fakes.HTTPRequest.member_req('', version=self.wsgi_api_version)
sgroup = server_group_template(unknown='unknown')
self.assertRaises(self.validation_error, self.controller.create,
req, body={'server_group': sgroup})
@@ -785,7 +789,7 @@ class ServerGroupTestV275(ServerGroupTestV264):
path='/os-server-groups?dummy=False&all_projects=True')
def test_list_server_group_additional_param(self):
- req = fakes.HTTPRequest.blank('/os-server-groups?dummy=False',
- version=self.wsgi_api_version)
+ req = fakes.HTTPRequest.reader_req('/os-server-groups?dummy=False',
+ version=self.wsgi_api_version)
self.assertRaises(self.validation_error, self.controller.index,
req)
diff --git a/nova/tests/unit/api/openstack/compute/test_server_metadata.py b/nova/tests/unit/api/openstack/compute/test_server_metadata.py
index a454597305..9b420dde17 100644
--- a/nova/tests/unit/api/openstack/compute/test_server_metadata.py
+++ b/nova/tests/unit/api/openstack/compute/test_server_metadata.py
@@ -13,7 +13,8 @@
# License for the specific language governing permissions and limitations
# under the License.
-import mock
+from unittest import mock
+
from oslo_config import cfg
from oslo_serialization import jsonutils
from oslo_utils.fixture import uuidsentinel as uuids
diff --git a/nova/tests/unit/api/openstack/compute/test_server_migrations.py b/nova/tests/unit/api/openstack/compute/test_server_migrations.py
index 8d798d434c..c5d8556751 100644
--- a/nova/tests/unit/api/openstack/compute/test_server_migrations.py
+++ b/nova/tests/unit/api/openstack/compute/test_server_migrations.py
@@ -15,8 +15,8 @@
import copy
import datetime
+from unittest import mock
-import mock
from oslo_utils.fixture import uuidsentinel as uuids
import webob
diff --git a/nova/tests/unit/api/openstack/compute/test_server_password.py b/nova/tests/unit/api/openstack/compute/test_server_password.py
index e34ceb90e9..2751eee709 100644
--- a/nova/tests/unit/api/openstack/compute/test_server_password.py
+++ b/nova/tests/unit/api/openstack/compute/test_server_password.py
@@ -13,7 +13,7 @@
# License for the specific language governing permissions and limitations
# under the License.
-import mock
+from unittest import mock
from nova.api.openstack.compute import server_password \
as server_password_v21
diff --git a/nova/tests/unit/api/openstack/compute/test_server_reset_state.py b/nova/tests/unit/api/openstack/compute/test_server_reset_state.py
index 3462cf21ac..3a0c9ca1e2 100644
--- a/nova/tests/unit/api/openstack/compute/test_server_reset_state.py
+++ b/nova/tests/unit/api/openstack/compute/test_server_reset_state.py
@@ -12,7 +12,8 @@
# License for the specific language governing permissions and limitations
# under the License.
-import mock
+from unittest import mock
+
from oslo_utils import uuidutils
import webob
diff --git a/nova/tests/unit/api/openstack/compute/test_server_start_stop.py b/nova/tests/unit/api/openstack/compute/test_server_start_stop.py
index 60d12d0c43..f604652622 100644
--- a/nova/tests/unit/api/openstack/compute/test_server_start_stop.py
+++ b/nova/tests/unit/api/openstack/compute/test_server_start_stop.py
@@ -12,7 +12,8 @@
# License for the specific language governing permissions and limitations
# under the License.
-import mock
+from unittest import mock
+
from oslo_utils.fixture import uuidsentinel as uuids
import webob
diff --git a/nova/tests/unit/api/openstack/compute/test_server_tags.py b/nova/tests/unit/api/openstack/compute/test_server_tags.py
index b121c75c3a..4e4609d778 100644
--- a/nova/tests/unit/api/openstack/compute/test_server_tags.py
+++ b/nova/tests/unit/api/openstack/compute/test_server_tags.py
@@ -10,7 +10,8 @@
# License for the specific language governing permissions and limitations
# under the License.
-import mock
+from unittest import mock
+
from webob import exc
from nova.api.openstack.compute import server_tags
diff --git a/nova/tests/unit/api/openstack/compute/test_server_topology.py b/nova/tests/unit/api/openstack/compute/test_server_topology.py
index 3d8f6dc908..63d5f7a5c1 100644
--- a/nova/tests/unit/api/openstack/compute/test_server_topology.py
+++ b/nova/tests/unit/api/openstack/compute/test_server_topology.py
@@ -11,7 +11,8 @@
# License for the specific language governing permissions and limitations
# under the License.
-import mock
+from unittest import mock
+
from oslo_utils.fixture import uuidsentinel as uuids
from webob import exc
diff --git a/nova/tests/unit/api/openstack/compute/test_servers.py b/nova/tests/unit/api/openstack/compute/test_servers.py
index 31739ed7ab..8903de0c3c 100644
--- a/nova/tests/unit/api/openstack/compute/test_servers.py
+++ b/nova/tests/unit/api/openstack/compute/test_servers.py
@@ -17,13 +17,14 @@
import collections
import copy
import datetime
+from unittest import mock
+
import ddt
import functools
from urllib import parse as urlparse
import fixtures
import iso8601
-import mock
from oslo_policy import policy as oslo_policy
from oslo_serialization import base64
from oslo_serialization import jsonutils
@@ -2087,10 +2088,10 @@ class ServersControllerTestV216(_ServersControllerTest):
return server_dict
- @mock.patch('nova.compute.api.API.get_instance_host_status')
- def _verify_host_status_policy_behavior(self, func, mock_get_host_status):
+ def _verify_host_status_policy_behavior(self, func):
# Set policy to disallow both host_status cases and verify we don't
# call the get_instance_host_status compute RPC API.
+ self.mock_get_instance_host_status.reset_mock()
rules = {
'os_compute_api:servers:show:host_status': '!',
'os_compute_api:servers:show:host_status:unknown-only': '!',
@@ -2098,7 +2099,7 @@ class ServersControllerTestV216(_ServersControllerTest):
orig_rules = policy.get_rules()
policy.set_rules(oslo_policy.Rules.from_dict(rules), overwrite=False)
func()
- mock_get_host_status.assert_not_called()
+ self.mock_get_instance_host_status.assert_not_called()
# Restore the original rules.
policy.set_rules(orig_rules)
@@ -2638,15 +2639,13 @@ class ServersControllerTestV275(ControllerTest):
microversion = '2.75'
- @mock.patch('nova.compute.api.API.get_all')
- def test_get_servers_additional_query_param_old_version(self, mock_get):
+ def test_get_servers_additional_query_param_old_version(self):
req = fakes.HTTPRequest.blank(self.path_with_query % 'unknown=1',
use_admin_context=True,
version='2.74')
self.controller.index(req)
- @mock.patch('nova.compute.api.API.get_all')
- def test_get_servers_ignore_sort_key_old_version(self, mock_get):
+ def test_get_servers_ignore_sort_key_old_version(self):
req = fakes.HTTPRequest.blank(
self.path_with_query % 'sort_key=deleted',
use_admin_context=True, version='2.74')
@@ -3584,13 +3583,13 @@ class ServersControllerRebuildTestV263(ControllerTest):
},
}
- @mock.patch('nova.compute.api.API.get')
- def _rebuild_server(self, mock_get, certs=None,
- conf_enabled=True, conf_certs=None):
+ def _rebuild_server(self, certs=None, conf_enabled=True, conf_certs=None):
ctx = self.req.environ['nova.context']
- mock_get.return_value = fakes.stub_instance_obj(ctx,
- vm_state=vm_states.ACTIVE, trusted_certs=certs,
- project_id=self.req_project_id, user_id=self.req_user_id)
+ self.mock_get.side_effect = None
+ self.mock_get.return_value = fakes.stub_instance_obj(
+ ctx, vm_state=vm_states.ACTIVE, trusted_certs=certs,
+ project_id=self.req_project_id, user_id=self.req_user_id
+ )
self.flags(default_trusted_certificate_ids=conf_certs, group='glance')
@@ -3743,10 +3742,10 @@ class ServersControllerRebuildTestV271(ControllerTest):
}
}
- @mock.patch('nova.compute.api.API.get')
- def _rebuild_server(self, mock_get):
+ def _rebuild_server(self):
ctx = self.req.environ['nova.context']
- mock_get.return_value = fakes.stub_instance_obj(ctx,
+ self.mock_get.side_effect = None
+ self.mock_get.return_value = fakes.stub_instance_obj(ctx,
vm_state=vm_states.ACTIVE, project_id=self.req_project_id,
user_id=self.req_user_id)
server = self.controller._action_rebuild(
@@ -8023,7 +8022,7 @@ class ServersViewBuilderTestV269(_ServersViewBuilderTest):
version=self.microversion)
def test_get_server_list_detail_with_down_cells(self):
- # Fake out 1 partially constructued instance and one full instance.
+ # Fake out 1 partially constructed instance and one full instance.
self.instances = [
self.instance,
objects.Instance(
@@ -8151,7 +8150,7 @@ class ServersViewBuilderTestV269(_ServersViewBuilderTest):
self.assertThat(output, matchers.DictMatches(expected))
def test_get_server_list_with_down_cells(self):
- # Fake out 1 partially constructued instance and one full instance.
+ # Fake out 1 partially constructed instance and one full instance.
self.instances = [
self.instance,
objects.Instance(
@@ -8203,7 +8202,7 @@ class ServersViewBuilderTestV269(_ServersViewBuilderTest):
self.assertThat(output, matchers.DictMatches(expected))
def test_get_server_with_down_cells(self):
- # Fake out 1 partially constructued instance.
+ # Fake out 1 partially constructed instance.
self.instance = objects.Instance(
context=self.ctxt,
uuid=self.uuid,
@@ -8266,7 +8265,7 @@ class ServersViewBuilderTestV269(_ServersViewBuilderTest):
self.assertThat(output, matchers.DictMatches(expected))
def test_get_server_without_image_avz_user_id_set_from_down_cells(self):
- # Fake out 1 partially constructued instance.
+ # Fake out 1 partially constructed instance.
self.instance = objects.Instance(
context=self.ctxt,
uuid=self.uuid,
diff --git a/nova/tests/unit/api/openstack/compute/test_services.py b/nova/tests/unit/api/openstack/compute/test_services.py
index 5d83bc5a91..f237acc15a 100644
--- a/nova/tests/unit/api/openstack/compute/test_services.py
+++ b/nova/tests/unit/api/openstack/compute/test_services.py
@@ -14,9 +14,9 @@
import copy
import datetime
+from unittest import mock
from keystoneauth1 import exceptions as ks_exc
-import mock
from oslo_utils import fixture as utils_fixture
from oslo_utils.fixture import uuidsentinel
import webob.exc
diff --git a/nova/tests/unit/api/openstack/compute/test_shelve.py b/nova/tests/unit/api/openstack/compute/test_shelve.py
index 68e523be47..bfa8d2d055 100644
--- a/nova/tests/unit/api/openstack/compute/test_shelve.py
+++ b/nova/tests/unit/api/openstack/compute/test_shelve.py
@@ -12,10 +12,10 @@
# License for the specific language governing permissions and limitations
# under the License.
-import fixtures
-import mock
+from unittest import mock
import ddt
+import fixtures
from oslo_serialization import jsonutils
from oslo_utils.fixture import uuidsentinel as uuids
import webob
@@ -134,13 +134,17 @@ class UnshelveServerControllerTestV277(test.NoDBTestCase):
'availability_zone': 'us-east'
}}
self.req.body = jsonutils.dump_as_bytes(body)
- self.req.api_version_request = (api_version_request.
- APIVersionRequest('2.76'))
- with mock.patch.object(self.controller.compute_api,
- 'unshelve') as mock_unshelve:
+ self.req.api_version_request = (
+ api_version_request.APIVersionRequest('2.76')
+ )
+ with mock.patch.object(
+ self.controller.compute_api, 'unshelve'
+ ) as mock_unshelve:
self.controller._unshelve(self.req, fakes.FAKE_UUID, body=body)
mock_unshelve.assert_called_once_with(
- self.req.environ['nova.context'], instance, new_az=None)
+ self.req.environ['nova.context'],
+ instance,
+ )
@mock.patch('nova.compute.api.API.unshelve')
@mock.patch('nova.api.openstack.common.get_instance')
@@ -158,7 +162,9 @@ class UnshelveServerControllerTestV277(test.NoDBTestCase):
APIVersionRequest('2.76'))
self.controller._unshelve(self.req, fakes.FAKE_UUID, body=body)
mock_unshelve.assert_called_once_with(
- self.req.environ['nova.context'], instance, new_az=None)
+ self.req.environ['nova.context'],
+ instance,
+ )
@mock.patch('nova.compute.api.API.unshelve')
@mock.patch('nova.api.openstack.common.get_instance')
@@ -193,6 +199,238 @@ class UnshelveServerControllerTestV277(test.NoDBTestCase):
'availability_zone': None
}}
self.req.body = jsonutils.dump_as_bytes(body)
+ self.assertRaises(
+ exception.ValidationError,
+ self.controller._unshelve,
+ self.req,
+ fakes.FAKE_UUID, body=body)
+
+ def test_unshelve_with_additional_param(self):
+ body = {
+ 'unshelve': {
+ 'availability_zone': 'us-east',
+ 'additional_param': 1
+ }}
+ self.req.body = jsonutils.dump_as_bytes(body)
+ exc = self.assertRaises(
+ exception.ValidationError,
+ self.controller._unshelve, self.req,
+ fakes.FAKE_UUID, body=body)
+ self.assertIn("Additional properties are not allowed", str(exc))
+
+
+class UnshelveServerControllerTestV291(test.NoDBTestCase):
+ """Server controller test for microversion 2.91
+
+ Add host parameter to unshelve a shelved-offloaded server of
+ 2.91 microversion.
+ """
+ wsgi_api_version = '2.91'
+
+ def setUp(self):
+ super(UnshelveServerControllerTestV291, self).setUp()
+ self.controller = shelve_v21.ShelveController()
+ self.req = fakes.HTTPRequest.blank(
+ '/%s/servers/a/action' % fakes.FAKE_PROJECT_ID,
+ use_admin_context=True, version=self.wsgi_api_version)
+
+ def fake_get_instance(self):
+ ctxt = self.req.environ['nova.context']
+ return fake_instance.fake_instance_obj(
+ ctxt, uuid=fakes.FAKE_UUID, vm_state=vm_states.SHELVED_OFFLOADED)
+
+ @mock.patch('nova.api.openstack.common.get_instance')
+ def test_unshelve_with_az_pre_2_91(self, mock_get_instance):
+ """Make sure specifying an AZ before microversion 2.91
+ is still working.
+ """
+ instance = self.fake_get_instance()
+ mock_get_instance.return_value = instance
+
+ body = {
+ 'unshelve': {
+ 'availability_zone': 'us-east',
+ }}
+ self.req.body = jsonutils.dump_as_bytes(body)
+ self.req.api_version_request = (
+ api_version_request.APIVersionRequest('2.77'))
+ with mock.patch.object(
+ self.controller.compute_api, 'unshelve'
+ ) as mock_unshelve:
+ self.controller._unshelve(self.req, fakes.FAKE_UUID, body=body)
+ mock_unshelve.assert_called_once_with(
+ self.req.environ['nova.context'],
+ instance,
+ new_az='us-east',
+ )
+
+ @mock.patch('nova.api.openstack.common.get_instance')
+ def test_unshelve_without_parameters_2_91(self, mock_get_instance):
+ """Make sure not specifying parameters with microversion 2.91
+ is working.
+ """
+ instance = self.fake_get_instance()
+ mock_get_instance.return_value = instance
+
+ body = {
+ 'unshelve': None
+ }
+ self.req.body = jsonutils.dump_as_bytes(body)
+ self.req.api_version_request = (
+ api_version_request.APIVersionRequest('2.91'))
+ with mock.patch.object(
+ self.controller.compute_api, 'unshelve') as mock_unshelve:
+ self.controller._unshelve(self.req, fakes.FAKE_UUID, body=body)
+ mock_unshelve.assert_called_once_with(
+ self.req.environ['nova.context'],
+ instance,
+ )
+
+ @mock.patch('nova.api.openstack.common.get_instance')
+ def test_unshelve_with_az_2_91(self, mock_get_instance):
+ """Make sure specifying an AZ with microversion 2.91
+ is working.
+ """
+ instance = self.fake_get_instance()
+ mock_get_instance.return_value = instance
+
+ body = {
+ 'unshelve': {
+ 'availability_zone': 'us-east',
+ }}
+ self.req.body = jsonutils.dump_as_bytes(body)
+ self.req.api_version_request = (
+ api_version_request.APIVersionRequest('2.91'))
+ with mock.patch.object(
+ self.controller.compute_api, 'unshelve') as mock_unshelve:
+ self.controller._unshelve(self.req, fakes.FAKE_UUID, body=body)
+ mock_unshelve.assert_called_once_with(
+ self.req.environ['nova.context'],
+ instance,
+ new_az='us-east',
+ host=None,
+ )
+
+ @mock.patch('nova.api.openstack.common.get_instance')
+ def test_unshelve_with_az_none_2_91(self, mock_get_instance):
+ """Make sure specifying an AZ to none (unpin server)
+ is working.
+ """
+ instance = self.fake_get_instance()
+ mock_get_instance.return_value = instance
+
+ body = {
+ 'unshelve': {
+ 'availability_zone': None,
+ }}
+ self.req.body = jsonutils.dump_as_bytes(body)
+ self.req.api_version_request = (
+ api_version_request.APIVersionRequest('2.91'))
+ with mock.patch.object(
+ self.controller.compute_api, 'unshelve') as mock_unshelve:
+ self.controller._unshelve(self.req, fakes.FAKE_UUID, body=body)
+ mock_unshelve.assert_called_once_with(
+ self.req.environ['nova.context'],
+ instance,
+ new_az=None,
+ host=None,
+ )
+
+ @mock.patch('nova.api.openstack.common.get_instance')
+ def test_unshelve_with_host_2_91(self, mock_get_instance):
+ """Make sure specifying a host with microversion 2.91
+ is working.
+ """
+ instance = self.fake_get_instance()
+ mock_get_instance.return_value = instance
+
+ body = {
+ 'unshelve': {
+ 'host': 'server02',
+ }}
+ self.req.body = jsonutils.dump_as_bytes(body)
+ self.req.api_version_request = (
+ api_version_request.APIVersionRequest('2.91'))
+ with mock.patch.object(
+ self.controller.compute_api, 'unshelve') as mock_unshelve:
+ self.controller._unshelve(self.req, fakes.FAKE_UUID, body=body)
+ mock_unshelve.assert_called_once_with(
+ self.req.environ['nova.context'],
+ instance,
+ host='server02',
+ )
+
+ @mock.patch('nova.compute.api.API.unshelve')
+ @mock.patch('nova.api.openstack.common.get_instance')
+ def test_unshelve_with_az_and_host_with_v2_91(
+ self, mock_get_instance, mock_unshelve):
+ """Make sure specifying a host and an availability_zone with
+ microversion 2.91 is working.
+ """
+ instance = self.fake_get_instance()
+ mock_get_instance.return_value = instance
+
+ body = {
+ 'unshelve': {
+ 'availability_zone': 'us-east',
+ 'host': 'server01',
+ }}
+ self.req.body = jsonutils.dump_as_bytes(body)
+ self.req.api_version_request = (
+ api_version_request.APIVersionRequest('2.91'))
+
+ self.controller._unshelve(self.req, fakes.FAKE_UUID, body=body)
+ self.controller.compute_api.unshelve.assert_called_once_with(
+ self.req.environ['nova.context'],
+ instance,
+ new_az='us-east',
+ host='server01',
+ )
+
+ def test_invalid_az_name_with_int(self):
+ body = {
+ 'unshelve': {
+ 'host': 1234
+ }}
+ self.req.body = jsonutils.dump_as_bytes(body)
+ self.assertRaises(
+ exception.ValidationError,
+ self.controller._unshelve,
+ self.req,
+ fakes.FAKE_UUID,
+ body=body)
+
+ def test_no_az_value(self):
+ body = {
+ 'unshelve': {
+ 'host': None
+ }}
+ self.req.body = jsonutils.dump_as_bytes(body)
+ self.assertRaises(
+ exception.ValidationError,
+ self.controller._unshelve,
+ self.req,
+ fakes.FAKE_UUID, body=body)
+
+ def test_invalid_host_fqdn_with_int(self):
+ body = {
+ 'unshelve': {
+ 'host': 1234
+ }}
+ self.req.body = jsonutils.dump_as_bytes(body)
+ self.assertRaises(
+ exception.ValidationError,
+ self.controller._unshelve,
+ self.req,
+ fakes.FAKE_UUID,
+ body=body)
+
+ def test_no_host(self):
+ body = {
+ 'unshelve': {
+ 'host': None
+ }}
+ self.req.body = jsonutils.dump_as_bytes(body)
self.assertRaises(exception.ValidationError,
self.controller._unshelve,
self.req, fakes.FAKE_UUID,
@@ -201,7 +439,7 @@ class UnshelveServerControllerTestV277(test.NoDBTestCase):
def test_unshelve_with_additional_param(self):
body = {
'unshelve': {
- 'availability_zone': 'us-east',
+ 'host': 'server01',
'additional_param': 1
}}
self.req.body = jsonutils.dump_as_bytes(body)
@@ -209,4 +447,4 @@ class UnshelveServerControllerTestV277(test.NoDBTestCase):
exception.ValidationError,
self.controller._unshelve, self.req,
fakes.FAKE_UUID, body=body)
- self.assertIn("Additional properties are not allowed", str(exc))
+ self.assertIn("Invalid input for field/attribute unshelve.", str(exc))
diff --git a/nova/tests/unit/api/openstack/compute/test_simple_tenant_usage.py b/nova/tests/unit/api/openstack/compute/test_simple_tenant_usage.py
index 5794fdf061..a7dcfae558 100644
--- a/nova/tests/unit/api/openstack/compute/test_simple_tenant_usage.py
+++ b/nova/tests/unit/api/openstack/compute/test_simple_tenant_usage.py
@@ -14,8 +14,8 @@
# under the License.
import datetime
+from unittest import mock
-import mock
from oslo_utils.fixture import uuidsentinel as uuids
from oslo_utils import timeutils
import webob
diff --git a/nova/tests/unit/api/openstack/compute/test_snapshots.py b/nova/tests/unit/api/openstack/compute/test_snapshots.py
index b23ed50865..2e133506a3 100644
--- a/nova/tests/unit/api/openstack/compute/test_snapshots.py
+++ b/nova/tests/unit/api/openstack/compute/test_snapshots.py
@@ -13,7 +13,8 @@
# License for the specific language governing permissions and limitations
# under the License.
-import mock
+from unittest import mock
+
import webob
from nova.api.openstack.compute import volumes as volumes_v21
diff --git a/nova/tests/unit/api/openstack/compute/test_suspend_server.py b/nova/tests/unit/api/openstack/compute/test_suspend_server.py
index 6eeb2b4549..a44297362c 100644
--- a/nova/tests/unit/api/openstack/compute/test_suspend_server.py
+++ b/nova/tests/unit/api/openstack/compute/test_suspend_server.py
@@ -12,8 +12,9 @@
# License for the specific language governing permissions and limitations
# under the License.
+from unittest import mock
+
import ddt
-import mock
from oslo_utils.fixture import uuidsentinel as uuids
import webob
diff --git a/nova/tests/unit/api/openstack/compute/test_tenant_networks.py b/nova/tests/unit/api/openstack/compute/test_tenant_networks.py
index d05c85c508..c6de561b11 100644
--- a/nova/tests/unit/api/openstack/compute/test_tenant_networks.py
+++ b/nova/tests/unit/api/openstack/compute/test_tenant_networks.py
@@ -13,8 +13,8 @@
# under the License.
import copy
+from unittest import mock
-import mock
from oslo_config import cfg
from oslo_utils.fixture import uuidsentinel as uuids
import webob
diff --git a/nova/tests/unit/api/openstack/compute/test_volumes.py b/nova/tests/unit/api/openstack/compute/test_volumes.py
index a24c104c93..5b4a2d8b1a 100644
--- a/nova/tests/unit/api/openstack/compute/test_volumes.py
+++ b/nova/tests/unit/api/openstack/compute/test_volumes.py
@@ -15,10 +15,10 @@
# under the License.
import datetime
+from unittest import mock
import urllib
import fixtures
-import mock
from oslo_serialization import jsonutils
from oslo_utils import encodeutils
from oslo_utils.fixture import uuidsentinel as uuids
@@ -1889,8 +1889,7 @@ class AssistedSnapshotDeleteTestCaseV21(test.NoDBTestCase):
req, '5')
def _test_assisted_delete_instance_conflict(self, api_error):
- # unset the stub on volume_snapshot_delete from setUp
- self.mock_volume_snapshot_delete.stop()
+ self.mock_volume_snapshot_delete.side_effect = api_error
params = {
'delete_info': jsonutils.dumps({'volume_id': '1'}),
}
@@ -1899,10 +1898,9 @@ class AssistedSnapshotDeleteTestCaseV21(test.NoDBTestCase):
urllib.parse.urlencode(params),
version=self.microversion)
req.method = 'DELETE'
- with mock.patch.object(compute_api.API, 'volume_snapshot_delete',
- side_effect=api_error):
- self.assertRaises(
- webob.exc.HTTPBadRequest, self.controller.delete, req, '5')
+
+ self.assertRaises(
+ webob.exc.HTTPBadRequest, self.controller.delete, req, '5')
def test_assisted_delete_instance_invalid_state(self):
api_error = exception.InstanceInvalidState(
diff --git a/nova/tests/unit/api/openstack/fakes.py b/nova/tests/unit/api/openstack/fakes.py
index 8cf90ddebe..9ac970f787 100644
--- a/nova/tests/unit/api/openstack/fakes.py
+++ b/nova/tests/unit/api/openstack/fakes.py
@@ -240,6 +240,9 @@ class HTTPRequest(os_wsgi.Request):
def blank(cls, *args, **kwargs):
defaults = {'base_url': 'http://localhost/v2'}
use_admin_context = kwargs.pop('use_admin_context', False)
+ roles = kwargs.pop('roles', [])
+ if use_admin_context:
+ roles.append('admin')
project_id = kwargs.pop('project_id', FAKE_PROJECT_ID)
version = kwargs.pop('version', os_wsgi.DEFAULT_API_VERSION)
defaults.update(kwargs)
@@ -247,10 +250,19 @@ class HTTPRequest(os_wsgi.Request):
out.environ['nova.context'] = FakeRequestContext(
user_id='fake_user',
project_id=project_id,
- is_admin=use_admin_context)
+ is_admin=use_admin_context,
+ roles=roles)
out.api_version_request = api_version.APIVersionRequest(version)
return out
+ @classmethod
+ def member_req(cls, *args, **kwargs):
+ return cls.blank(*args, roles=['member', 'reader'], **kwargs)
+
+ @classmethod
+ def reader_req(cls, *args, **kwargs):
+ return cls.blank(*args, roles=['reader'], **kwargs)
+
class HTTPRequestV21(HTTPRequest):
pass
diff --git a/nova/tests/unit/api/openstack/test_common.py b/nova/tests/unit/api/openstack/test_common.py
index 4666413e27..7fe98bd52e 100644
--- a/nova/tests/unit/api/openstack/test_common.py
+++ b/nova/tests/unit/api/openstack/test_common.py
@@ -17,7 +17,8 @@
Test suites for 'common' code used throughout the OpenStack HTTP API.
"""
-import mock
+from unittest import mock
+
from testtools import matchers
import webob
import webob.exc
diff --git a/nova/tests/unit/api/openstack/test_faults.py b/nova/tests/unit/api/openstack/test_faults.py
index 1bd56a87c5..c7dd5c0a9d 100644
--- a/nova/tests/unit/api/openstack/test_faults.py
+++ b/nova/tests/unit/api/openstack/test_faults.py
@@ -14,7 +14,8 @@
# License for the specific language governing permissions and limitations
# under the License.
-import mock
+from unittest import mock
+
from oslo_serialization import jsonutils
import webob
import webob.dec
diff --git a/nova/tests/unit/api/openstack/test_requestlog.py b/nova/tests/unit/api/openstack/test_requestlog.py
index 0ea91439cc..7e79e1b079 100644
--- a/nova/tests/unit/api/openstack/test_requestlog.py
+++ b/nova/tests/unit/api/openstack/test_requestlog.py
@@ -13,7 +13,7 @@
# License for the specific language governing permissions and limitations
# under the License.
-import mock
+from unittest import mock
import fixtures as fx
import testtools
diff --git a/nova/tests/unit/api/openstack/test_wsgi.py b/nova/tests/unit/api/openstack/test_wsgi.py
index e0cf8f6fd8..76554e1fcb 100644
--- a/nova/tests/unit/api/openstack/test_wsgi.py
+++ b/nova/tests/unit/api/openstack/test_wsgi.py
@@ -10,7 +10,8 @@
# License for the specific language governing permissions and limitations
# under the License.
-import mock
+from unittest import mock
+
from oslo_serialization import jsonutils
import testscenarios
import webob
diff --git a/nova/tests/unit/api/openstack/test_wsgi_app.py b/nova/tests/unit/api/openstack/test_wsgi_app.py
index 247886b9dd..0eb7011c11 100644
--- a/nova/tests/unit/api/openstack/test_wsgi_app.py
+++ b/nova/tests/unit/api/openstack/test_wsgi_app.py
@@ -11,9 +11,9 @@
# under the License.
import tempfile
+from unittest import mock
import fixtures
-import mock
from oslo_config import fixture as config_fixture
from oslotest import base
@@ -104,3 +104,18 @@ document_root = /tmp
'disable_compute_service_check_for_ffu', True,
group='workarounds')
wsgi_app._setup_service('myhost', 'api')
+
+ def test__get_config_files_empty_env(self):
+ env = {}
+ result = wsgi_app._get_config_files(env)
+ expected = ['/etc/nova/api-paste.ini', '/etc/nova/nova.conf']
+ self.assertEqual(result, expected)
+
+ def test__get_config_files_with_env(self):
+ env = {
+ "OS_NOVA_CONFIG_DIR": "/nova",
+ "OS_NOVA_CONFIG_FILES": "api.conf",
+ }
+ result = wsgi_app._get_config_files(env)
+ expected = ['/nova/api.conf']
+ self.assertEqual(result, expected)