From: wanghao Date: Sun, 15 Feb 2015 07:40:53 +0000 (+0800) Subject: Non-admin user to query volume filter by az X-Git-Url: https://review.fuel-infra.org/gitweb?a=commitdiff_plain;h=1d122d8152ac317ef976da6d446e8dd76a84adcd;p=openstack-build%2Fcinder-build.git Non-admin user to query volume filter by az Now cinder limits non-admin user to query volume just filtered by 'name', 'status', and 'metadata', those are hard coded in cinder-api. So improve this using config option and allow non-admin to query volume filtered by 'availability zone'. DocImpact Change-Id: Ia4a324959e16d7e6effe7afb18fe57562231d879 Implements: blueprint allow-non-admin-to-query-volume-filter-by-az --- diff --git a/cinder/api/v2/volumes.py b/cinder/api/v2/volumes.py index 13a86009c..50d0d3c6f 100644 --- a/cinder/api/v2/volumes.py +++ b/cinder/api/v2/volumes.py @@ -18,6 +18,7 @@ import ast +from oslo_config import cfg from oslo_log import log as logging from oslo_utils import uuidutils import webob @@ -37,6 +38,18 @@ from cinder.volume import utils as volume_utils from cinder.volume import volume_types +query_volume_filters_opt = cfg.ListOpt('query_volume_filters', + default=['name', 'status', 'metadata', + 'availability_zone'], + help="Volume filter options which " + "non-admin user could use to " + "query volumes. Default values " + "are: ['name', 'status', " + "'metadata', 'availability_zone']") + +CONF = cfg.CONF +CONF.register_opt(query_volume_filters_opt) + LOG = logging.getLogger(__name__) SCHEDULER_HINTS_NAMESPACE =\ "http://docs.openstack.org/block-service/ext/scheduler-hints/api/v2" @@ -436,7 +449,7 @@ class VolumeController(wsgi.Controller): def _get_volume_filter_options(self): """Return volume search options allowed by non-admin.""" - return ('name', 'status', 'metadata') + return CONF.query_volume_filters @wsgi.serializers(xml=VolumeTemplate) def update(self, req, id, body): diff --git a/cinder/tests/unit/api/v2/test_volumes.py b/cinder/tests/unit/api/v2/test_volumes.py index d74154b55..8f7cfc48d 100644 --- a/cinder/tests/unit/api/v2/test_volumes.py +++ b/cinder/tests/unit/api/v2/test_volumes.py @@ -1565,6 +1565,66 @@ class VolumeApiTest(test.TestCase): sort_keys=['created_at'], sort_dirs=['desc'], filters={'display_name': 'd-'}, viewable_admin_meta=True) + @mock.patch('cinder.volume.api.API.get_all') + def test_get_volumes_filter_with_status(self, get_all): + req = mock.MagicMock() + ctxt = context.RequestContext('fake', 'fake', auth_token=True) + req.environ = {'cinder.context': ctxt} + req.params = {'status': 'available'} + self.controller._view_builder.detail_list = mock.Mock() + self.controller._get_volumes(req, True) + get_all.assert_called_once_with( + ctxt, None, None, + sort_keys=['created_at'], sort_dirs=['desc'], + filters={'status': 'available'}, viewable_admin_meta=True) + + @mock.patch('cinder.volume.api.API.get_all') + def test_get_volumes_filter_with_metadata(self, get_all): + req = mock.MagicMock() + ctxt = context.RequestContext('fake', 'fake', auth_token=True) + req.environ = {'cinder.context': ctxt} + req.params = {'metadata': "{'fake_key': 'fake_value'}"} + self.controller._view_builder.detail_list = mock.Mock() + self.controller._get_volumes(req, True) + get_all.assert_called_once_with( + ctxt, None, None, + sort_keys=['created_at'], sort_dirs=['desc'], + filters={'metadata': {'fake_key': 'fake_value'}}, + viewable_admin_meta=True) + + @mock.patch('cinder.volume.api.API.get_all') + def test_get_volumes_filter_with_availability_zone(self, get_all): + req = mock.MagicMock() + ctxt = context.RequestContext('fake', 'fake', auth_token=True) + req.environ = {'cinder.context': ctxt} + req.params = {'availability_zone': 'nova'} + self.controller._view_builder.detail_list = mock.Mock() + self.controller._get_volumes(req, True) + get_all.assert_called_once_with( + ctxt, None, None, + sort_keys=['created_at'], sort_dirs=['desc'], + filters={'availability_zone': 'nova'}, viewable_admin_meta=True) + + @mock.patch('cinder.volume.api.API.get_all') + def test_get_volumes_filter_with_invalid_filter(self, get_all): + req = mock.MagicMock() + ctxt = context.RequestContext('fake', 'fake', auth_token=True) + req.environ = {'cinder.context': ctxt} + req.params = {'invalid_filter': 'invalid', + 'availability_zone': 'nova'} + self.controller._view_builder.detail_list = mock.Mock() + self.controller._get_volumes(req, True) + get_all.assert_called_once_with( + ctxt, None, None, + sort_keys=['created_at'], sort_dirs=['desc'], + filters={'availability_zone': 'nova'}, viewable_admin_meta=True) + + def test_get_volume_filter_options_using_config(self): + self.override_config('query_volume_filters', ['name', 'status', + 'metadata']) + self.assertEqual(['name', 'status', 'metadata'], + self.controller._get_volume_filter_options()) + class VolumeSerializerTest(test.TestCase): def _verify_volume_attachment(self, attach, tree):