]> review.fuel-infra Code Review - openstack-build/cinder-build.git/commitdiff
Non-admin user to query volume filter by az
authorwanghao <wanghao749@huawei.com>
Sun, 15 Feb 2015 07:40:53 +0000 (15:40 +0800)
committerwanghao <wanghao749@huawei.com>
Tue, 2 Jun 2015 06:12:10 +0000 (06:12 +0000)
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

cinder/api/v2/volumes.py
cinder/tests/unit/api/v2/test_volumes.py

index 13a86009cf5f02d71e45c0e2e038404993fa7fd4..50d0d3c6fe5c3910f3f1293cfc0515feb4899e3b 100644 (file)
@@ -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):
index d74154b554009fa4df9debd50a0c340ea21b8756..8f7cfc48d1368d0fb152a8a330e6220963b305ef 100644 (file)
@@ -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):