From abab99c0eb57ceef1c9701000c16c0616fba3e2b Mon Sep 17 00:00:00 2001 From: jiaopengju Date: Sun, 18 Nov 2018 19:46:47 +0800 Subject: [PATCH] Add all tenants support for checkpoints listing Change-Id: Ic02a60a0eec1e7d3b0ca7b1a355a5d62d5c0046c Implements: bp checkpoint-all-tenants --- karbor/api/v1/providers.py | 9 ++- karbor/services/protection/api.py | 5 +- karbor/services/protection/checkpoint.py | 68 +++++++++++++++---- karbor/services/protection/manager.py | 6 +- karbor/services/protection/provider.py | 6 +- karbor/services/protection/rpcapi.py | 6 +- .../protection/test_checkpoint_collection.py | 55 +++++++++++++++ ...ing-with-all-tenants-d7b0d1a149cb690d.yaml | 4 ++ 8 files changed, 134 insertions(+), 25 deletions(-) create mode 100644 releasenotes/notes/checkpoints-listing-with-all-tenants-d7b0d1a149cb690d.yaml diff --git a/karbor/api/v1/providers.py b/karbor/api/v1/providers.py index 679e4686..095ffa53 100644 --- a/karbor/api/v1/providers.py +++ b/karbor/api/v1/providers.py @@ -311,7 +311,8 @@ class ProvidersController(wsgi.Controller): if filters is None: filters = {} - + all_tenants = utils.get_bool_param( + 'all_tenants', filters) and context.is_admin try: if limit is not None: limit = int(limit) @@ -325,12 +326,16 @@ class ProvidersController(wsgi.Controller): if filters: LOG.debug("Searching by: %s.", six.text_type(filters)) + if all_tenants: + del filters['all_tenants'] checkpoints = self.protection_api.list_checkpoints( context, provider_id, marker, limit, sort_keys=sort_keys, sort_dirs=sort_dirs, filters=filters, - offset=offset) + offset=offset, + all_tenants=all_tenants + ) LOG.info("Get all checkpoints completed successfully.") return checkpoints diff --git a/karbor/services/protection/api.py b/karbor/services/protection/api.py index 369d067e..d8c01efe 100644 --- a/karbor/services/protection/api.py +++ b/karbor/services/protection/api.py @@ -52,7 +52,7 @@ class API(base.Base): ) def list_checkpoints(self, context, provider_id, marker, limit, - sort_keys, sort_dirs, filters, offset): + sort_keys, sort_dirs, filters, offset, all_tenants): return self.protection_rpcapi.list_checkpoints( context, provider_id, @@ -60,7 +60,8 @@ class API(base.Base): limit, sort_keys, sort_dirs, - filters + filters, + all_tenants ) def list_protectable_types(self, context): diff --git a/karbor/services/protection/checkpoint.py b/karbor/services/protection/checkpoint.py index 72cbf245..003f9af8 100644 --- a/karbor/services/protection/checkpoint.py +++ b/karbor/services/protection/checkpoint.py @@ -303,9 +303,49 @@ class CheckpointCollection(object): self._checkpoints_section = bank.get_sub_section("/checkpoints") self._indices_section = bank.get_sub_section("/indices") + @staticmethod + def _get_prefix_and_marker_by_provider(provider_id, project_id, marker, + marker_checkpoint, all_tenants): + if all_tenants: + prefix = "/by-provider/%s/" % provider_id + marker = "/%s/%s" % ( + marker_checkpoint["project_id"], marker) if marker else marker + else: + prefix = "/by-provider/%s/%s/" % (provider_id, project_id) + marker = "/%s" % marker if marker else marker + return prefix, marker + + @staticmethod + def _get_prefix_and_marker_by_plan(plan_id, project_id, marker, + marker_checkpoint, all_tenants): + if all_tenants: + prefix = "/by-plan/%s/" % plan_id + marker = "/%s/%s/%s" % ( + marker_checkpoint["project_id"], + marker_checkpoint["created_at"], marker) if marker else marker + else: + prefix = "/by-plan/%s/%s/" % (plan_id, project_id) + marker = "/%s/%s" % ( + marker_checkpoint["created_at"], marker) if marker else marker + return prefix, marker + + @staticmethod + def _get_prefix_and_marker_by_date(project_id, marker, marker_checkpoint, + all_tenants): + prefix = "/by-date/" + if all_tenants: + marker = "/%s/%s/%s" % ( + marker_checkpoint["created_at"], + marker_checkpoint["project_id"], marker) if marker else marker + else: + marker = "/%s/%s/%s" % ( + marker_checkpoint["created_at"], project_id, + marker) if marker else marker + return prefix, marker + def list_ids(self, project_id, provider_id, limit=None, marker=None, plan_id=None, start_date=None, end_date=None, sort_dir=None, - context=None): + context=None, all_tenants=False): marker_checkpoint = None if marker is not None: checkpoint_section = self._checkpoints_section.get_sub_section( @@ -319,25 +359,22 @@ class CheckpointCollection(object): end_date = timeutils.utcnow() if plan_id is None and start_date is None: - prefix = "/by-provider/%s/%s/" % (provider_id, project_id) - if marker is not None: - marker = "/%s" % marker + prefix, marker = self._get_prefix_and_marker_by_provider( + provider_id, project_id, marker, + marker_checkpoint, all_tenants) elif plan_id is not None: - prefix = "/by-plan/%s/%s/" % (plan_id, project_id) - if marker is not None: - date = marker_checkpoint["created_at"] - marker = "/%s/%s" % (date, marker) + prefix, marker = self._get_prefix_and_marker_by_plan( + plan_id, project_id, marker, marker_checkpoint, all_tenants) else: - prefix = "/by-date/" - if marker is not None: - date = marker_checkpoint["created_at"] - marker = "/%s/%s/%s" % (date, project_id, marker) + prefix, marker = self._get_prefix_and_marker_by_date( + project_id, marker, marker_checkpoint, all_tenants) return self._list_ids(project_id, prefix, limit, marker, start_date, - end_date, sort_dir, context=context) + end_date, sort_dir, context=context, + all_tenants=all_tenants) def _list_ids(self, project_id, prefix, limit, marker, start_date, - end_date, sort_dir, context=None): + end_date, sort_dir, context=None, all_tenants=False): if start_date is None: return [key[key.find("@") + 1:] for key in self._indices_section.list_objects( @@ -359,7 +396,8 @@ class CheckpointCollection(object): key.split("/")[date_cursor], "%Y-%m-%d") checkpoint_project_id = key.split("/")[project_id_cursor] if start_date <= date <= end_date and ( - checkpoint_project_id == project_id): + all_tenants or ( + checkpoint_project_id == project_id)): ids.append(key[key.find("@") + 1:]) if limit is not None and len(ids) == limit: return ids diff --git a/karbor/services/protection/manager.py b/karbor/services/protection/manager.py index 4ffcad1e..59aafcfb 100644 --- a/karbor/services/protection/manager.py +++ b/karbor/services/protection/manager.py @@ -369,7 +369,8 @@ class ProtectionManager(manager.Manager): exception.CheckpointNotFound, exception.BankListObjectsFailed) def list_checkpoints(self, context, provider_id, marker=None, limit=None, - sort_keys=None, sort_dirs=None, filters=None): + sort_keys=None, sort_dirs=None, filters=None, + all_tenants=False): LOG.info("Starting list checkpoints. provider_id:%s", provider_id) plan_id = filters.get("plan_id", None) start_date = None @@ -380,13 +381,14 @@ class ProtectionManager(manager.Manager): if filters.get("end_date", None): end_date = datetime.strptime( filters.get("end_date"), "%Y-%m-%d") + sort_dir = None if sort_dirs is None else sort_dirs[0] provider = self.provider_registry.show_provider(provider_id) project_id = context.project_id checkpoint_ids = provider.list_checkpoints( project_id, provider_id, limit=limit, marker=marker, plan_id=plan_id, start_date=start_date, end_date=end_date, - sort_dir=sort_dir, context=context) + sort_dir=sort_dir, context=context, all_tenants=all_tenants) checkpoints = [] for checkpoint_id in checkpoint_ids: checkpoint = provider.get_checkpoint(checkpoint_id, diff --git a/karbor/services/protection/provider.py b/karbor/services/protection/provider.py index 359f95fe..0ed0109f 100755 --- a/karbor/services/protection/provider.py +++ b/karbor/services/protection/provider.py @@ -150,12 +150,14 @@ class PluggableProtectionProvider(object): def list_checkpoints(self, project_id, provider_id, limit=None, marker=None, plan_id=None, start_date=None, - end_date=None, sort_dir=None, context=None): + end_date=None, sort_dir=None, context=None, + all_tenants=False): checkpoint_collection = self.get_checkpoint_collection() return checkpoint_collection.list_ids( project_id=project_id, provider_id=provider_id, limit=limit, marker=marker, plan_id=plan_id, start_date=start_date, - end_date=end_date, sort_dir=sort_dir, context=context) + end_date=end_date, sort_dir=sort_dir, context=context, + all_tenants=all_tenants) class ProviderRegistry(object): diff --git a/karbor/services/protection/rpcapi.py b/karbor/services/protection/rpcapi.py index 8e3de813..7fd2f81d 100644 --- a/karbor/services/protection/rpcapi.py +++ b/karbor/services/protection/rpcapi.py @@ -92,7 +92,7 @@ class ProtectionAPI(object): def list_checkpoints(self, ctxt, provider_id, marker=None, limit=None, sort_keys=None, - sort_dirs=None, filters=None): + sort_dirs=None, filters=None, all_tenants=False): cctxt = self.client.prepare(version='1.0') return cctxt.call( ctxt, @@ -102,7 +102,9 @@ class ProtectionAPI(object): limit=limit, sort_keys=sort_keys, sort_dirs=sort_dirs, - filters=filters) + filters=filters, + all_tenants=all_tenants + ) def list_protectable_types(self, ctxt): cctxt = self.client.prepare(version='1.0') diff --git a/karbor/tests/unit/protection/test_checkpoint_collection.py b/karbor/tests/unit/protection/test_checkpoint_collection.py index 5f10d4d1..4232eb04 100644 --- a/karbor/tests/unit/protection/test_checkpoint_collection.py +++ b/karbor/tests/unit/protection/test_checkpoint_collection.py @@ -47,6 +47,23 @@ class CheckpointCollectionTest(base.TestCase): self.assertEqual(set(collection.list_ids( project_id=project_id, provider_id=provider_id)), result) + def test_list_checkpoints_with_all_tenants(self): + collection = self._create_test_collection() + plan_1 = fake_protection_plan() + plan_1["id"] = "fake_plan_id_1" + plan_1["project_id"] = "fake_project_id_1" + provider_id_1 = plan_1['provider_id'] + checkpoints_plan_1 = {collection.create(plan_1).id for i in range(10)} + + plan_2 = fake_protection_plan() + plan_2["id"] = "fake_plan_id_2" + plan_2["project_id"] = "fake_project_id_2" + checkpoints_plan_2 = {collection.create(plan_2).id for i in range(10)} + checkpoints_plan_1.update(checkpoints_plan_2) + self.assertEqual(set(collection.list_ids( + project_id="fake_project_id_1", provider_id=provider_id_1, + all_tenants=True)), checkpoints_plan_1) + def test_list_checkpoints_by_plan_id(self): collection = self._create_test_collection() plan_1 = fake_protection_plan() @@ -69,6 +86,21 @@ class CheckpointCollectionTest(base.TestCase): project_id="fake_project_id_2", provider_id=provider_id_2, plan_id="fake_plan_id_2")), checkpoints_plan_2) + def test_list_checkpoints_by_plan_with_all_tenants(self): + collection = self._create_test_collection() + plan_1 = fake_protection_plan() + plan_1["id"] = "fake_plan_id_1" + plan_1["project_id"] = "fake_project_id_1" + provider_id_1 = plan_1['provider_id'] + checkpoints_plan_1 = {collection.create(plan_1).id for i in range(10)} + plan_1["project_id"] = "fake_project_id_2" + checkpoints_plan_2 = {collection.create(plan_1).id for i in range(10)} + checkpoints_plan_2.update(checkpoints_plan_1) + self.assertEqual(set(collection.list_ids( + project_id="fake_project_id_1", provider_id=provider_id_1, + plan_id='fake_plan_id_1', + all_tenants=True)), checkpoints_plan_2) + def test_list_checkpoints_by_plan_id_and_filter_by_start_date(self): collection = self._create_test_collection() date1 = datetime.strptime("2018-11-12", "%Y-%m-%d") @@ -135,6 +167,29 @@ class CheckpointCollectionTest(base.TestCase): end_date=date2)), checkpoints_date_2) + def test_list_checkpoints_by_date_with_all_tenants(self): + collection = self._create_test_collection() + date1 = datetime.strptime("2018-11-15", "%Y-%m-%d") + timeutils.utcnow = mock.MagicMock() + timeutils.utcnow.return_value = date1 + plan_1 = fake_protection_plan() + plan_1["id"] = "fake_plan_id_1" + plan_1["project_id"] = "fake_project_id_1" + provider_id_1 = plan_1['provider_id'] + checkpoints_1 = {collection.create(plan_1).id for i in range(10)} + + date2 = datetime.strptime("2018-11-17", "%Y-%m-%d") + timeutils.utcnow = mock.MagicMock() + timeutils.utcnow.return_value = date2 + plan_1["id"] = "fake_plan_id_2" + plan_1["project_id"] = "fake_project_id_2" + checkpoints_2 = {collection.create(plan_1).id for i in range(10)} + checkpoints_2.update(checkpoints_1) + self.assertEqual(set(collection.list_ids( + project_id="fake_project_id_1", provider_id=provider_id_1, + start_date=date1, + all_tenants=True)), checkpoints_2) + def test_list_checkpoints_by_date_with_marker(self): collection = self._create_test_collection() date = datetime.strptime("2018-11-12", "%Y-%m-%d") diff --git a/releasenotes/notes/checkpoints-listing-with-all-tenants-d7b0d1a149cb690d.yaml b/releasenotes/notes/checkpoints-listing-with-all-tenants-d7b0d1a149cb690d.yaml new file mode 100644 index 00000000..fe08e3b3 --- /dev/null +++ b/releasenotes/notes/checkpoints-listing-with-all-tenants-d7b0d1a149cb690d.yaml @@ -0,0 +1,4 @@ +--- +features: + - | + Add support for listing checkpoints by admin with all_tenants.