diff --git a/nova/api/openstack/compute/hosts.py b/nova/api/openstack/compute/hosts.py index ba5fac3db853..a2eac66a9c19 100644 --- a/nova/api/openstack/compute/hosts.py +++ b/nova/api/openstack/compute/hosts.py @@ -40,6 +40,7 @@ class HostController(wsgi.Controller): super(HostController, self).__init__() @wsgi.Controller.api_version("2.1", "2.42") + @validation.query_schema(hosts.index_query) @extensions.expected_errors(()) def index(self, req): """Returns a dict in the format diff --git a/nova/api/openstack/compute/schemas/hosts.py b/nova/api/openstack/compute/schemas/hosts.py index 3905fc63aa2d..e708e8a1ca31 100644 --- a/nova/api/openstack/compute/schemas/hosts.py +++ b/nova/api/openstack/compute/schemas/hosts.py @@ -12,6 +12,8 @@ # License for the specific language governing permissions and limitations # under the License. +from nova.api.validation import parameter_types + update = { 'type': 'object', 'properties': { @@ -34,3 +36,15 @@ update = { }, 'additionalProperties': False } + +index_query = { + 'type': 'object', + 'properties': { + 'zone': parameter_types.multi_params({'type': 'string'}) + }, + # NOTE(gmann): This is kept True to keep backward compatibility. + # As of now Schema validation stripped out the additional parameters and + # does not raise 400. In the future, we may block the additional parameters + # by bump in Microversion. + 'additionalProperties': True +} diff --git a/nova/tests/unit/api/openstack/compute/test_hosts.py b/nova/tests/unit/api/openstack/compute/test_hosts.py index 308202e8b1d9..b7a85d9a3fe0 100644 --- a/nova/tests/unit/api/openstack/compute/test_hosts.py +++ b/nova/tests/unit/api/openstack/compute/test_hosts.py @@ -17,7 +17,6 @@ import mock import testtools import webob.exc -from nova.api.openstack import api_version_request as api_version from nova.api.openstack.compute import hosts as os_hosts_v21 from nova.compute import power_state from nova.compute import vm_states @@ -129,12 +128,6 @@ def _create_instance_dict(**kwargs): return inst -class FakeRequestWithNovaZone(object): - environ = {"nova.context": context_maker.get_admin_context()} - GET = {"zone": "nova"} - api_version_request = api_version.APIVersionRequest('2.1') - - class HostTestCaseV21(test.TestCase): """Test Case for hosts.""" validation_ex = exception.ValidationError @@ -178,6 +171,49 @@ class HostTestCaseV21(test.TestCase): hosts = result['hosts'] self.assertEqual(fake_hosts.HOST_LIST, hosts) + def test_list_host_with_multi_filter(self): + query_string = 'zone=nova1&zone=nova' + req = fakes.HTTPRequest.blank('', use_admin_context=True, + query_string=query_string) + result = self.controller.index(req) + self.assertIn('hosts', result) + hosts = result['hosts'] + self.assertEqual(fake_hosts.HOST_LIST_NOVA_ZONE, hosts) + + def test_list_host_query_allow_negative_int_as_string(self): + req = fakes.HTTPRequest.blank('', use_admin_context=True, + query_string='zone=-1') + result = self.controller.index(req) + self.assertIn('hosts', result) + hosts = result['hosts'] + self.assertEqual([], hosts) + + def test_list_host_query_allow_int_as_string(self): + req = fakes.HTTPRequest.blank('', use_admin_context=True, + query_string='zone=123') + result = self.controller.index(req) + self.assertIn('hosts', result) + hosts = result['hosts'] + self.assertEqual([], hosts) + + def test_list_host_with_unknown_filter(self): + query_string = 'unknown_filter=abc' + req = fakes.HTTPRequest.blank('', use_admin_context=True, + query_string=query_string) + result = self.controller.index(req) + self.assertIn('hosts', result) + hosts = result['hosts'] + self.assertEqual(fake_hosts.HOST_LIST, hosts) + + def test_list_host_with_hypervisor_and_additional_filter(self): + query_string = 'zone=nova&additional_filter=nova2' + req = fakes.HTTPRequest.blank('', use_admin_context=True, + query_string=query_string) + result = self.controller.index(req) + self.assertIn('hosts', result) + hosts = result['hosts'] + self.assertEqual(fake_hosts.HOST_LIST_NOVA_ZONE, hosts) + def test_disable_host(self): self._test_host_update('host_c1', 'status', 'disable', 'disabled') self._test_host_update('host_c2', 'status', 'disable', 'enabled') @@ -383,7 +419,10 @@ class HostTestCaseV21(test.TestCase): self.controller.show, self.req, s_ref['host']) def test_list_hosts_with_zone(self): - result = self.controller.index(FakeRequestWithNovaZone()) + query_string = 'zone=nova' + req = fakes.HTTPRequest.blank('', use_admin_context=True, + query_string=query_string) + result = self.controller.index(req) self.assertIn('hosts', result) hosts = result['hosts'] self.assertEqual(fake_hosts.HOST_LIST_NOVA_ZONE, hosts)