def _get_consistencygroups(self, req, is_detail):
"""Returns a list of consistency groups through view builder."""
context = req.environ['cinder.context']
- consistencygroups = self.consistencygroup_api.get_all(context)
- limited_list = common.limited(consistencygroups, req)
+ filters = req.params.copy()
+ marker, limit, offset = common.get_pagination_params(filters)
+ sort_keys, sort_dirs = common.get_sort_params(filters)
+
+ consistencygroups = self.consistencygroup_api.get_all(
+ context, filters=filters, marker=marker, limit=limit,
+ offset=offset, sort_keys=sort_keys, sort_dirs=sort_dirs)
if is_detail:
- consistencygroups = self._view_builder.detail_list(req,
- limited_list)
+ consistencygroups = self._view_builder.detail_list(
+ req, consistencygroups)
else:
- consistencygroups = self._view_builder.summary_list(req,
- limited_list)
+ consistencygroups = self._view_builder.summary_list(
+ req, consistencygroups)
return consistencygroups
@wsgi.response(202)
consistencygroups_list = [
func(request, consistencygroup)['consistencygroup']
for consistencygroup in consistencygroups]
+ cg_links = self._get_collection_links(request,
+ consistencygroups,
+ self._collection_name)
consistencygroups_dict = dict(consistencygroups=consistencygroups_list)
+ if cg_links:
+ consistencygroups_dict['consistencygroup_links'] = cg_links
return consistencygroups_dict
check_policy(context, 'get', group)
return group
- def get_all(self, context, marker=None, limit=None, sort_key='created_at',
- sort_dir='desc', filters=None):
+ def get_all(self, context, filters=None, marker=None, limit=None,
+ offset=None, sort_keys=None, sort_dirs=None):
check_policy(context, 'get_all')
if filters is None:
filters = {}
- try:
- if limit is not None:
- limit = int(limit)
- if limit < 0:
- msg = _('limit param must be positive')
- raise exception.InvalidInput(reason=msg)
- except ValueError:
- msg = _('limit param must be an integer')
- raise exception.InvalidInput(reason=msg)
-
if filters:
LOG.debug("Searching by: %s", filters)
if (context.is_admin and 'all_tenants' in filters):
- groups = objects.ConsistencyGroupList.get_all(context)
+ del filters['all_tenants']
+ groups = objects.ConsistencyGroupList.get_all(
+ context, filters=filters, marker=marker, limit=limit,
+ offset=offset, sort_keys=sort_keys, sort_dirs=sort_dirs)
else:
groups = objects.ConsistencyGroupList.get_all_by_project(
- context, context.project_id)
+ context, context.project_id, filters=filters, marker=marker,
+ limit=limit, offset=offset, sort_keys=sort_keys,
+ sort_dirs=sort_dirs)
return groups
def create_cgsnapshot(self, context, group, name, description):
return IMPL.consistencygroup_get(context, consistencygroup_id)
-def consistencygroup_get_all(context):
+def consistencygroup_get_all(context, filters=None, marker=None, limit=None,
+ offset=None, sort_keys=None, sort_dirs=None):
"""Get all consistencygroups."""
- return IMPL.consistencygroup_get_all(context)
+ return IMPL.consistencygroup_get_all(context, filters=filters,
+ marker=marker, limit=limit,
+ offset=offset, sort_keys=sort_keys,
+ sort_dirs=sort_dirs)
def consistencygroup_create(context, values):
return IMPL.consistencygroup_create(context, values)
-def consistencygroup_get_all_by_project(context, project_id):
+def consistencygroup_get_all_by_project(context, project_id, filters=None,
+ marker=None, limit=None, offset=None,
+ sort_keys=None, sort_dirs=None):
"""Get all consistencygroups belonging to a project."""
- return IMPL.consistencygroup_get_all_by_project(context, project_id)
+ return IMPL.consistencygroup_get_all_by_project(context, project_id,
+ filters=filters,
+ marker=marker, limit=limit,
+ offset=offset,
+ sort_keys=sort_keys,
+ sort_dirs=sort_dirs)
def consistencygroup_update(context, consistencygroup_id, values):
return _consistencygroup_get(context, consistencygroup_id)
+def _consistencygroups_get_query(context, session=None, project_only=False):
+ return model_query(context, models.ConsistencyGroup, session=session,
+ project_only=project_only)
+
+
+def _process_consistencygroups_filters(query, filters):
+ if filters:
+ # Ensure that filters' keys exist on the model
+ if not is_valid_model_filters(models.ConsistencyGroup, filters):
+ return
+ query = query.filter_by(**filters)
+ return query
+
+
+def _consistencygroup_get_all(context, filters=None, marker=None, limit=None,
+ offset=None, sort_keys=None, sort_dirs=None):
+ if filters and not is_valid_model_filters(models.ConsistencyGroup,
+ filters):
+ return []
+
+ session = get_session()
+ with session.begin():
+ # Generate the paginate query
+ query = _generate_paginate_query(context, session, marker,
+ limit, sort_keys, sort_dirs, filters,
+ offset, models.ConsistencyGroup)
+ if query is None:
+ return []
+ return query.all()
+
+
@require_admin_context
-def consistencygroup_get_all(context):
- return model_query(context, models.ConsistencyGroup).all()
+def consistencygroup_get_all(context, filters=None, marker=None, limit=None,
+ offset=None, sort_keys=None, sort_dirs=None):
+ """Retrieves all consistency groups.
+
+ If no sort parameters are specified then the returned cgs are sorted
+ first by the 'created_at' key and then by the 'id' key in descending
+ order.
+
+ :param context: context to query under
+ :param marker: the last item of the previous page, used to determine the
+ next page of results to return
+ :param limit: maximum number of items to return
+ :param sort_keys: list of attributes by which results should be sorted,
+ paired with corresponding item in sort_dirs
+ :param sort_dirs: list of directions in which results should be sorted,
+ paired with corresponding item in sort_keys
+ :param filters: dictionary of filters; values that are in lists, tuples,
+ or sets cause an 'IN' operation, while exact matching
+ is used for other values, see
+ _process_consistencygroups_filters function for more
+ information
+ :returns: list of matching consistency groups
+ """
+ return _consistencygroup_get_all(context, filters, marker, limit, offset,
+ sort_keys, sort_dirs)
@require_context
-def consistencygroup_get_all_by_project(context, project_id):
+def consistencygroup_get_all_by_project(context, project_id, filters=None,
+ marker=None, limit=None, offset=None,
+ sort_keys=None, sort_dirs=None):
+ """Retrieves all consistency groups in a project.
+
+ If no sort parameters are specified then the returned cgs are sorted
+ first by the 'created_at' key and then by the 'id' key in descending
+ order.
+
+ :param context: context to query under
+ :param marker: the last item of the previous page, used to determine the
+ next page of results to return
+ :param limit: maximum number of items to return
+ :param sort_keys: list of attributes by which results should be sorted,
+ paired with corresponding item in sort_dirs
+ :param sort_dirs: list of directions in which results should be sorted,
+ paired with corresponding item in sort_keys
+ :param filters: dictionary of filters; values that are in lists, tuples,
+ or sets cause an 'IN' operation, while exact matching
+ is used for other values, see
+ _process_consistencygroups_filters function for more
+ information
+ :returns: list of matching consistency groups
+ """
authorize_project_context(context, project_id)
+ if not filters:
+ filters = {}
+ else:
+ filters = filters.copy()
- return model_query(context, models.ConsistencyGroup).\
- filter_by(project_id=project_id).all()
+ filters['project_id'] = project_id
+ return _consistencygroup_get_all(context, filters, marker, limit, offset,
+ sort_keys, sort_dirs)
@require_context
models.QualityOfServiceSpecs: (_qos_specs_get_query,
_process_qos_specs_filters, _qos_specs_get),
models.VolumeTypes: (_volume_type_get_query, _process_volume_types_filters,
- _volume_type_get_db_object)
+ _volume_type_get_db_object),
+ models.ConsistencyGroup: (_consistencygroups_get_query,
+ _process_consistencygroups_filters,
+ _consistencygroup_get)
}
@base.CinderObjectRegistry.register
class ConsistencyGroupList(base.ObjectListBase, base.CinderObject):
- VERSION = '1.0'
+ # Version 1.0: Initial version
+ # Version 1.1: Add pagination support to consistency group
+ VERSION = '1.1'
fields = {
'objects': fields.ListOfObjectsField('ConsistencyGroup')
}
child_version = {
- '1.0': '1.0'
+ '1.0': '1.0',
+ '1.1': '1.1',
}
@base.remotable_classmethod
- def get_all(cls, context):
- consistencygroups = db.consistencygroup_get_all(context)
+ def get_all(cls, context, filters=None, marker=None, limit=None,
+ offset=None, sort_keys=None, sort_dirs=None):
+ consistencygroups = db.consistencygroup_get_all(
+ context, filters=filters, marker=marker, limit=limit,
+ offset=offset, sort_keys=sort_keys, sort_dirs=sort_dirs)
return base.obj_make_list(context, cls(context),
objects.ConsistencyGroup,
consistencygroups)
@base.remotable_classmethod
- def get_all_by_project(cls, context, project_id):
- consistencygroups = db.consistencygroup_get_all_by_project(context,
- project_id)
+ def get_all_by_project(cls, context, project_id, filters=None, marker=None,
+ limit=None, offset=None, sort_keys=None,
+ sort_dirs=None):
+ consistencygroups = db.consistencygroup_get_all_by_project(
+ context, project_id, filters=filters, marker=marker, limit=limit,
+ offset=offset, sort_keys=sort_keys, sort_dirs=sort_dirs)
return base.obj_make_list(context, cls(context),
objects.ConsistencyGroup,
consistencygroups)
Tests for consistency group code.
"""
+import ddt
import json
from xml.dom import minidom
from cinder.volume import api as volume_api
+@ddt.ddt
class ConsistencyGroupsAPITestCase(test.TestCase):
"""Test Case for consistency groups API."""
res_dict = json.loads(res.body)
self.assertEqual(200, res.status_int)
- self.assertEqual(consistencygroup1.id,
+ self.assertEqual(consistencygroup3.id,
res_dict['consistencygroups'][0]['id'])
self.assertEqual('test_consistencygroup',
res_dict['consistencygroups'][0]['name'])
res_dict['consistencygroups'][1]['id'])
self.assertEqual('test_consistencygroup',
res_dict['consistencygroups'][1]['name'])
- self.assertEqual(consistencygroup3.id,
+ self.assertEqual(consistencygroup1.id,
res_dict['consistencygroups'][2]['id'])
self.assertEqual('test_consistencygroup',
res_dict['consistencygroups'][2]['name'])
dom = minidom.parseString(res.body)
consistencygroup_list = dom.getElementsByTagName('consistencygroup')
- self.assertEqual(consistencygroup1.id,
+ self.assertEqual(consistencygroup3.id,
consistencygroup_list.item(0).getAttribute('id'))
self.assertEqual(consistencygroup2.id,
consistencygroup_list.item(1).getAttribute('id'))
- self.assertEqual(consistencygroup3.id,
+ self.assertEqual(consistencygroup1.id,
consistencygroup_list.item(2).getAttribute('id'))
consistencygroup3.destroy()
consistencygroup2.destroy()
consistencygroup1.destroy()
+ @ddt.data(False, True)
+ def test_list_consistencygroups_with_limit(self, is_detail):
+ consistencygroup1 = self._create_consistencygroup()
+ consistencygroup2 = self._create_consistencygroup()
+ consistencygroup3 = self._create_consistencygroup()
+ url = '/v2/fake/consistencygroups?limit=1'
+ if is_detail:
+ url = '/v2/fake/consistencygroups/detail?limit=1'
+ req = webob.Request.blank(url)
+ req.method = 'GET'
+ req.headers['Content-Type'] = 'application/json'
+ res = req.get_response(fakes.wsgi_app())
+ res_dict = json.loads(res.body)
+
+ self.assertEqual(200, res.status_int)
+ self.assertEqual(1, len(res_dict['consistencygroups']))
+ self.assertEqual(consistencygroup3.id,
+ res_dict['consistencygroups'][0]['id'])
+ next_link = ('http://localhost/v2/fake/consistencygroups?limit='
+ '1&marker=%s') % res_dict['consistencygroups'][0]['id']
+ self.assertEqual(next_link,
+ res_dict['consistencygroup_links'][0]['href'])
+ consistencygroup1.destroy()
+ consistencygroup2.destroy()
+ consistencygroup3.destroy()
+
+ @ddt.data(False, True)
+ def test_list_consistencygroups_with_offset(self, is_detail):
+ consistencygroup1 = self._create_consistencygroup()
+ consistencygroup2 = self._create_consistencygroup()
+ consistencygroup3 = self._create_consistencygroup()
+ url = '/v2/fake/consistencygroups?offset=1'
+ if is_detail:
+ url = '/v2/fake/consistencygroups/detail?offset=1'
+ req = webob.Request.blank(url)
+ req.method = 'GET'
+ req.headers['Content-Type'] = 'application/json'
+ res = req.get_response(fakes.wsgi_app())
+ res_dict = json.loads(res.body)
+
+ self.assertEqual(200, res.status_int)
+ self.assertEqual(2, len(res_dict['consistencygroups']))
+ self.assertEqual(consistencygroup2.id,
+ res_dict['consistencygroups'][0]['id'])
+ self.assertEqual(consistencygroup1.id,
+ res_dict['consistencygroups'][1]['id'])
+ consistencygroup1.destroy()
+ consistencygroup2.destroy()
+ consistencygroup3.destroy()
+
+ @ddt.data(False, True)
+ def test_list_consistencygroups_with_limit_and_offset(self, is_detail):
+ consistencygroup1 = self._create_consistencygroup()
+ consistencygroup2 = self._create_consistencygroup()
+ consistencygroup3 = self._create_consistencygroup()
+ url = '/v2/fake/consistencygroups?limit=2&offset=1'
+ if is_detail:
+ url = '/v2/fake/consistencygroups/detail?limit=2&offset=1'
+ req = webob.Request.blank(url)
+ req.method = 'GET'
+ req.headers['Content-Type'] = 'application/json'
+ res = req.get_response(fakes.wsgi_app())
+ res_dict = json.loads(res.body)
+
+ self.assertEqual(200, res.status_int)
+ self.assertEqual(2, len(res_dict['consistencygroups']))
+ self.assertEqual(consistencygroup2.id,
+ res_dict['consistencygroups'][0]['id'])
+ self.assertEqual(consistencygroup1.id,
+ res_dict['consistencygroups'][1]['id'])
+ consistencygroup1.destroy()
+ consistencygroup2.destroy()
+ consistencygroup3.destroy()
+
+ @ddt.data(False, True)
+ def test_list_consistencygroups_with_filter(self, is_detail):
+ consistencygroup1 = self._create_consistencygroup()
+ consistencygroup2 = self._create_consistencygroup()
+ common_ctxt = context.RequestContext('fake', 'fake', auth_token=True,
+ is_admin=False)
+ consistencygroup3 = self._create_consistencygroup(ctxt=common_ctxt)
+ url = ('/v2/fake/consistencygroups?'
+ 'all_tenants=True&id=%s') % consistencygroup3.id
+ if is_detail:
+ url = ('/v2/fake/consistencygroups/detail?'
+ 'all_tenants=True&id=%s') % consistencygroup3.id
+ req = webob.Request.blank(url)
+ req.method = 'GET'
+ req.headers['Content-Type'] = 'application/json'
+ res = req.get_response(fakes.wsgi_app(fake_auth_context=self.ctxt))
+ res_dict = json.loads(res.body)
+
+ self.assertEqual(200, res.status_int)
+ self.assertEqual(1, len(res_dict['consistencygroups']))
+ self.assertEqual(consistencygroup3.id,
+ res_dict['consistencygroups'][0]['id'])
+ consistencygroup1.destroy()
+ consistencygroup2.destroy()
+ consistencygroup3.destroy()
+
+ @ddt.data(False, True)
+ def test_list_consistencygroups_with_sort(self, is_detail):
+ consistencygroup1 = self._create_consistencygroup()
+ consistencygroup2 = self._create_consistencygroup()
+ consistencygroup3 = self._create_consistencygroup()
+ url = '/v2/fake/consistencygroups?sort=id:asc'
+ if is_detail:
+ url = '/v2/fake/consistencygroups/detail?sort=id:asc'
+ req = webob.Request.blank(url)
+ req.method = 'GET'
+ req.headers['Content-Type'] = 'application/json'
+ res = req.get_response(fakes.wsgi_app())
+ res_dict = json.loads(res.body)
+ expect_result = [consistencygroup1.id, consistencygroup2.id,
+ consistencygroup3.id]
+ expect_result.sort()
+
+ self.assertEqual(200, res.status_int)
+ self.assertEqual(3, len(res_dict['consistencygroups']))
+ self.assertEqual(expect_result[0],
+ res_dict['consistencygroups'][0]['id'])
+ self.assertEqual(expect_result[1],
+ res_dict['consistencygroups'][1]['id'])
+ self.assertEqual(expect_result[2],
+ res_dict['consistencygroups'][2]['id'])
+ consistencygroup1.destroy()
+ consistencygroup2.destroy()
+ consistencygroup3.destroy()
+
def test_list_consistencygroups_detail_json(self):
consistencygroup1 = self._create_consistencygroup()
consistencygroup2 = self._create_consistencygroup()
res_dict['consistencygroups'][0]['description'])
self.assertEqual('test_consistencygroup',
res_dict['consistencygroups'][0]['name'])
- self.assertEqual(consistencygroup1.id,
+ self.assertEqual(consistencygroup3.id,
res_dict['consistencygroups'][0]['id'])
self.assertEqual('creating',
res_dict['consistencygroups'][0]['status'])
- self.assertEqual(['123456'],
+ self.assertEqual(['uuid1', 'uuid2'],
res_dict['consistencygroups'][0]['volume_types'])
self.assertEqual('az1',
res_dict['consistencygroups'][2]['description'])
self.assertEqual('test_consistencygroup',
res_dict['consistencygroups'][2]['name'])
- self.assertEqual(consistencygroup3.id,
+ self.assertEqual(consistencygroup1.id,
res_dict['consistencygroups'][2]['id'])
self.assertEqual('creating',
res_dict['consistencygroups'][2]['status'])
- self.assertEqual(['uuid1', 'uuid2'],
+ self.assertEqual(['123456'],
res_dict['consistencygroups'][2]['volume_types'])
consistencygroup1.destroy()
'test_consistencygroup',
consistencygroup_detail.item(0).getAttribute('name'))
self.assertEqual(
- consistencygroup1.id,
+ consistencygroup3.id,
consistencygroup_detail.item(0).getAttribute('id'))
self.assertEqual(
'creating',
'test_consistencygroup',
consistencygroup_detail.item(2).getAttribute('name'))
self.assertEqual(
- consistencygroup3.id,
+ consistencygroup1.id,
consistencygroup_detail.item(2).getAttribute('id'))
self.assertEqual(
'creating',
self.assertEqual(1, len(consistencygroups))
TestConsistencyGroup._compare(self, fake_consistencygroup,
consistencygroups[0])
+
+ @mock.patch('cinder.db.consistencygroup_get_all',
+ return_value=[fake_consistencygroup])
+ def test_get_all_with_pagination(self, consistencygroup_get_all):
+ consistencygroups = objects.ConsistencyGroupList.get_all(
+ self.context, filters={'id': 'fake'}, marker=None, limit=1,
+ offset=None, sort_keys='id', sort_dirs='asc')
+ self.assertEqual(1, len(consistencygroups))
+ consistencygroup_get_all.assert_called_once_with(
+ self.context, filters={'id': 'fake'}, marker=None, limit=1,
+ offset=None, sort_keys='id', sort_dirs='asc')
+ TestConsistencyGroup._compare(self, fake_consistencygroup,
+ consistencygroups[0])
+
+ @mock.patch('cinder.db.consistencygroup_get_all_by_project',
+ return_value=[fake_consistencygroup])
+ def test_get_all_by_project_with_pagination(
+ self, consistencygroup_get_all_by_project):
+ consistencygroups = objects.ConsistencyGroupList.get_all_by_project(
+ self.context, self.project_id, filters={'id': 'fake'}, marker=None,
+ limit=1, offset=None, sort_keys='id', sort_dirs='asc')
+ self.assertEqual(1, len(consistencygroups))
+ consistencygroup_get_all_by_project.assert_called_once_with(
+ self.context, self.project_id, filters={'id': 'fake'}, marker=None,
+ limit=1, offset=None, sort_keys='id', sort_dirs='asc')
+ TestConsistencyGroup._compare(self, fake_consistencygroup,
+ consistencygroups[0])
'CGSnapshot': '1.0-190da2a2aa9457edc771d888f7d225c4',
'CGSnapshotList': '1.0-e8c3f4078cd0ee23487b34d173eec776',
'ConsistencyGroup': '1.2-ed7f90a6871991a19af716ade7337fc9',
- 'ConsistencyGroupList': '1.0-09d0aad5491e762ecfdf66bef02ceb8d',
+ 'ConsistencyGroupList': '1.1-73916823b697dfa0c7f02508d87e0f28',
'Service': '1.0-64baeb4911dbab1153064dd1c87edb9f',
'ServiceList': '1.0-d242d3384b68e5a5a534e090ff1d5161',
'Snapshot': '1.0-a6c33eefeadefb324d79f72f66c54e9a',