"""The volumes api."""
+import ast
import webob
from webob import exc
search_opts = {}
search_opts.update(req.GET)
+ if 'metadata' in search_opts:
+ search_opts['metadata'] = ast.literal_eval(search_opts['metadata'])
+
context = req.environ['cinder.context']
remove_invalid_options(context,
search_opts, self._get_volume_search_options())
def _get_volume_search_options(self):
"""Return volume search options allowed by non-admin."""
- return ('display_name', 'status')
+ return ('display_name', 'status', 'metadata')
@wsgi.serializers(xml=VolumeTemplate)
def update(self, req, id, body):
"""The volumes api."""
+import ast
import webob
from webob import exc
filters['display_name'] = filters['name']
del filters['name']
+ if 'metadata' in filters:
+ filters['metadata'] = ast.literal_eval(filters['metadata'])
+
volumes = self.volume_api.get_all(context, marker, limit, sort_key,
sort_dir, filters)
limited_list = common.limited(volumes, req)
def _get_volume_filter_options(self):
"""Return volume search options allowed by non-admin."""
- return ('name', 'status')
+ return ('name', 'status', 'metadata')
@wsgi.serializers(xml=VolumeTemplate)
def update(self, req, id, body):
from lxml import etree
from oslo.config import cfg
+import urllib
import webob
from cinder.api import extensions
resp = self.controller.index(req)
self.assertEqual(len(resp['volumes']), 0)
+ def test_volume_list_by_metadata(self):
+ def stub_volume_get_all_by_project(context, project_id, marker, limit,
+ sort_key, sort_dir):
+ return [
+ stubs.stub_volume(1, display_name='vol1',
+ status='available',
+ volume_metadata=[{'key': 'key1',
+ 'value': 'value1'}]),
+ stubs.stub_volume(2, display_name='vol2',
+ status='available',
+ volume_metadata=[{'key': 'key1',
+ 'value': 'value2'}]),
+ stubs.stub_volume(3, display_name='vol3',
+ status='in-use',
+ volume_metadata=[{'key': 'key1',
+ 'value': 'value2'}]),
+ ]
+ self.stubs.Set(db, 'volume_get_all_by_project',
+ stub_volume_get_all_by_project)
+
+ # no metadata filter
+ req = fakes.HTTPRequest.blank('/v1/volumes', use_admin_context=True)
+ resp = self.controller.index(req)
+ self.assertEqual(len(resp['volumes']), 3)
+
+ # single match
+ qparams = urllib.urlencode({'metadata': {'key1': 'value1'}})
+ req = fakes.HTTPRequest.blank('/v1/volumes?%s' % qparams,
+ use_admin_context=True)
+ resp = self.controller.index(req)
+ self.assertEqual(len(resp['volumes']), 1)
+ self.assertEqual(resp['volumes'][0]['display_name'], 'vol1')
+ self.assertEqual(resp['volumes'][0]['metadata']['key1'], 'value1')
+
+ # multiple matches
+ qparams = urllib.urlencode({'metadata': {'key1': 'value2'}})
+ req = fakes.HTTPRequest.blank('/v1/volumes?%s' % qparams,
+ use_admin_context=True)
+ resp = self.controller.index(req)
+ self.assertEqual(len(resp['volumes']), 2)
+ for volume in resp['volumes']:
+ self.assertEqual(volume['metadata']['key1'], 'value2')
+
+ # multiple filters
+ qparams = urllib.urlencode({'metadata': {'key1': 'value2'}})
+ req = fakes.HTTPRequest.blank('/v1/volumes?status=in-use&%s' % qparams,
+ use_admin_context=True)
+ resp = self.controller.index(req)
+ self.assertEqual(len(resp['volumes']), 1)
+ self.assertEqual(resp['volumes'][0]['display_name'], 'vol3')
+
+ # no match
+ qparams = urllib.urlencode({'metadata': {'key1': 'value3'}})
+ req = fakes.HTTPRequest.blank('/v1/volumes?%s' % qparams,
+ use_admin_context=True)
+ resp = self.controller.index(req)
+ self.assertEqual(len(resp['volumes']), 0)
+
def test_volume_list_by_status(self):
def stub_volume_get_all_by_project(context, project_id, marker, limit,
sort_key, sort_dir):
from lxml import etree
from oslo.config import cfg
+import urllib
import webob
from cinder.api import extensions
resp = self.controller.index(req)
self.assertEqual(len(resp['volumes']), 0)
+ def test_volume_list_by_metadata(self):
+ def stub_volume_get_all_by_project(context, project_id, marker, limit,
+ sort_key, sort_dir):
+ return [
+ stubs.stub_volume(1, display_name='vol1',
+ status='available',
+ volume_metadata=[{'key': 'key1',
+ 'value': 'value1'}]),
+ stubs.stub_volume(2, display_name='vol2',
+ status='available',
+ volume_metadata=[{'key': 'key1',
+ 'value': 'value2'}]),
+ stubs.stub_volume(3, display_name='vol3',
+ status='in-use',
+ volume_metadata=[{'key': 'key1',
+ 'value': 'value2'}]),
+ ]
+ self.stubs.Set(db, 'volume_get_all_by_project',
+ stub_volume_get_all_by_project)
+
+ # no metadata filter
+ req = fakes.HTTPRequest.blank('/v2/volumes', use_admin_context=True)
+ resp = self.controller.detail(req)
+ self.assertEqual(len(resp['volumes']), 3)
+
+ # single match
+ qparams = urllib.urlencode({'metadata': {'key1': 'value1'}})
+ req = fakes.HTTPRequest.blank('/v2/volumes?%s' % qparams,
+ use_admin_context=True)
+ resp = self.controller.detail(req)
+ self.assertEqual(len(resp['volumes']), 1)
+ self.assertEqual(resp['volumes'][0]['name'], 'vol1')
+ self.assertEqual(resp['volumes'][0]['metadata']['key1'], 'value1')
+
+ # multiple matches
+ qparams = urllib.urlencode({'metadata': {'key1': 'value2'}})
+ req = fakes.HTTPRequest.blank('/v2/volumes?%s' % qparams,
+ use_admin_context=True)
+ resp = self.controller.detail(req)
+ self.assertEqual(len(resp['volumes']), 2)
+ for volume in resp['volumes']:
+ self.assertEqual(volume['metadata']['key1'], 'value2')
+
+ # multiple filters
+ qparams = urllib.urlencode({'metadata': {'key1': 'value2'}})
+ req = fakes.HTTPRequest.blank('/v2/volumes?status=in-use&%s' % qparams,
+ use_admin_context=True)
+ resp = self.controller.detail(req)
+ self.assertEqual(len(resp['volumes']), 1)
+ self.assertEqual(resp['volumes'][0]['name'], 'vol3')
+
+ # no match
+ qparams = urllib.urlencode({'metadata': {'key1': 'value3'}})
+ req = fakes.HTTPRequest.blank('/v2/volumes?%s' % qparams,
+ use_admin_context=True)
+ resp = self.controller.detail(req)
+ self.assertEqual(len(resp['volumes']), 0)
+
def test_volume_list_by_status(self):
def stub_volume_get_all_by_project(context, project_id, marker, limit,
sort_key, sort_dir):