The Cinder db code already allows searching for a value in a list,
for example, id in ['id1', 'id2', 'id3']. The problem is when we
get the value at the API it comes as a string (e.g.
"['id1', 'id2', 'id3']", and therefore the filter fails. This was
already fixed for metadata filters, so just apply it to all filters.
We do a try/except because if it really is a string, then the
literal_eval will fail because we don't pass double quotes, such as
"'string'". The current code therefore will now cover lists and
fall back to the original behavior for strings.
Change-Id: Idfd8298401a330bb99ddcd130268fabb6ef9d162
Closes-Bug:
1403875
search_opts.pop('limit', None)
search_opts.pop('offset', None)
- if 'metadata' in search_opts:
- search_opts['metadata'] = ast.literal_eval(search_opts['metadata'])
+ for k, v in search_opts.iteritems():
+ try:
+ search_opts[k] = ast.literal_eval(v)
+ except ValueError:
+ LOG.debug('Could not evaluate value %s, assuming string', v)
context = req.environ['cinder.context']
utils.remove_invalid_filter_options(context,
filters['display_name'] = filters['name']
del filters['name']
- if 'metadata' in filters:
- filters['metadata'] = ast.literal_eval(filters['metadata'])
+ for k, v in filters.iteritems():
+ try:
+ filters[k] = ast.literal_eval(v)
+ except ValueError:
+ LOG.debug('Could not evaluate value %s, assuming string', v)
volumes = self.volume_api.get_all(context, marker, limit, sort_key,
sort_dir, filters,
import datetime
from lxml import etree
+import mock
from oslo.config import cfg
import webob
self.assertIn('volumes', res)
self.assertEqual(1, len(res['volumes']))
+ @mock.patch('cinder.utils.add_visible_admin_metadata')
+ @mock.patch('cinder.volume.api.API.get_all')
+ def test_get_volumes_filter_with_string(self, get_all, add_meta):
+ req = mock.MagicMock()
+ req.GET.copy.return_value = {'display_name': 'Volume-573108026'}
+ context = mock.Mock()
+ req.environ = {'cinder.context': context}
+ self.controller._items(req, mock.Mock)
+ get_all.assert_any_call(context, sort_dir='desc',
+ viewable_admin_meta=True,
+ sort_key='created_at',
+ limit=None,
+ filters={'display_name': 'Volume-573108026'},
+ marker=None)
+
+ @mock.patch('cinder.utils.add_visible_admin_metadata')
+ @mock.patch('cinder.volume.api.API.get_all')
+ def test_get_volumes_filter_with_list(self, get_all, add_meta):
+ req = mock.MagicMock()
+ req.GET.copy.return_value = {'id': "['1', '2', '3']"}
+ context = mock.Mock()
+ req.environ = {'cinder.context': context}
+ self.controller._items(req, mock.Mock)
+ get_all.assert_any_call(context, sort_dir='desc',
+ viewable_admin_meta=True,
+ sort_key='created_at',
+ limit=None, filters={'id': ['1', '2', '3']},
+ marker=None)
+
class VolumeSerializerTest(test.TestCase):
def _verify_volume_attachment(self, attach, tree):
import datetime
from lxml import etree
+import mock
from oslo.config import cfg
import six
import six.moves.urllib.parse as urlparse
body = {'volume': 'string'}
self._create_volume_bad_request(body=body)
+ @mock.patch('cinder.utils.add_visible_admin_metadata')
+ @mock.patch('cinder.volume.api.API.get_all')
+ def test_get_volumes_filter_with_string(self, get_all, add_meta):
+ req = mock.MagicMock()
+ context = mock.Mock()
+ req.environ = {'cinder.context': context}
+ req.params = {'display_name': 'Volume-573108026'}
+ self.controller._view_builder.detail_list = mock.Mock()
+ self.controller._get_volumes(req, True)
+ get_all.assert_any_call(context, None, None, 'created_at', 'desc',
+ {'display_name': 'Volume-573108026'},
+ viewable_admin_meta=True)
+
+ @mock.patch('cinder.utils.add_visible_admin_metadata')
+ @mock.patch('cinder.volume.api.API.get_all')
+ def test_get_volumes_filter_with_list(self, get_all, add_meta):
+ req = mock.MagicMock()
+ context = mock.Mock()
+ req.environ = {'cinder.context': context}
+ req.params = {'id': "['1', '2', '3']"}
+ self.controller._view_builder.detail_list = mock.Mock()
+ self.controller._get_volumes(req, True)
+ get_all.assert_any_call(context, None, None, 'created_at', 'desc',
+ {'id': ['1', '2', '3']},
+ viewable_admin_meta=True)
+
class VolumeSerializerTest(test.TestCase):
def _verify_volume_attachment(self, attach, tree):