From 3020cf5e5c9ff00b2c9c07fa2984980fe21321a9 Mon Sep 17 00:00:00 2001 From: okozachenko Date: Tue, 19 Apr 2022 19:00:43 +1000 Subject: Add the filter function in c-bak dashboard for both Project & Admin Change-Id: I09b0d12e489aad8da8e9ed3dee1b02a5abcb7355 --- openstack_dashboard/api/cinder.py | 13 +++-- .../dashboards/admin/backups/tables.py | 14 ++++- .../dashboards/admin/backups/tests.py | 62 ++++++++++++++++++++-- .../dashboards/admin/backups/views.py | 33 ++++++++++-- .../dashboards/project/backups/tables.py | 10 +++- 5 files changed, 119 insertions(+), 13 deletions(-) diff --git a/openstack_dashboard/api/cinder.py b/openstack_dashboard/api/cinder.py index 03ac5aee3..dc791f9aa 100644 --- a/openstack_dashboard/api/cinder.py +++ b/openstack_dashboard/api/cinder.py @@ -591,12 +591,15 @@ def volume_backup_list(request): @profiler.trace -def volume_backup_list_paged_with_page_menu(request, page_number=1, +def volume_backup_list_paged_with_page_menu(request, search_opts=None, + page_number=1, sort_dir="desc", all_tenants=False): backups = [] count = 0 pages_count = 0 + if search_opts is None: + search_opts = {} page_size = utils.get_page_size(request) c_client = cinderclient(request, '3.45') @@ -605,12 +608,12 @@ def volume_backup_list_paged_with_page_menu(request, page_number=1, offset = (page_number - 1) * page_size sort = 'created_at:' + sort_dir + search_opts['all_tenants'] = all_tenants + search_opts['offset'] = offset + search_opts['with_count'] = True bkps, count = c_client.backups.list(limit=page_size, sort=sort, - search_opts={ - 'with_count': True, - 'offset': offset, - 'all_tenants': all_tenants}) + search_opts=search_opts) if not bkps: return backups, page_size, count, pages_count diff --git a/openstack_dashboard/dashboards/admin/backups/tables.py b/openstack_dashboard/dashboards/admin/backups/tables.py index a61f4b0e9..4a17ae7b9 100644 --- a/openstack_dashboard/dashboards/admin/backups/tables.py +++ b/openstack_dashboard/dashboards/admin/backups/tables.py @@ -94,6 +94,18 @@ class UpdateVolumeBackupStatusAction(tables.LinkAction): "volume_extension:backup_admin_actions:reset_status"),) +class BackupsFilterAction(tables.FilterAction): + + filter_type = 'server' + filter_choices = ( + ('project', _("Project ="), True), + ('name', _("Backup Name ="), True), + ('size', _("Size(GiB) ="), True), + ('status', _("Status ="), True), + ('volume_id', _("Volume ID ="), True,), + ) + + class AdminBackupsTable(project_tables.BackupsTable): project = tables.Column("tenant_name", verbose_name=_("Project")) name = tables.Column("name", @@ -112,7 +124,7 @@ class AdminBackupsTable(project_tables.BackupsTable): pagination_param = 'page' status_columns = ("status",) row_class = UpdateRow - table_actions = (AdminDeleteBackup,) + table_actions = (AdminDeleteBackup, BackupsFilterAction,) row_actions = (AdminRestoreBackup, ForceDeleteBackup, AdminDeleteBackup, UpdateVolumeBackupStatusAction,) columns = ('project', 'name', 'description', 'size', 'status', diff --git a/openstack_dashboard/dashboards/admin/backups/tests.py b/openstack_dashboard/dashboards/admin/backups/tests.py index c247ab460..e6c99464e 100644 --- a/openstack_dashboard/dashboards/admin/backups/tests.py +++ b/openstack_dashboard/dashboards/admin/backups/tests.py @@ -33,15 +33,24 @@ class AdminVolumeBackupsViewTests(test.BaseAdminViewTests): 'volume_backup_list_paged_with_page_menu']}) def _test_backups_index_paginated(self, page_number, backups, url, page_size, total_of_entries, - number_of_pages, has_prev, has_more): + number_of_pages, has_prev, has_more, + search_opts=None): self.mock_volume_backup_list_paged_with_page_menu.return_value = [ backups, page_size, total_of_entries, number_of_pages] self.mock_volume_list.return_value = self.cinder_volumes.list() self.mock_volume_snapshot_list.return_value \ = self.cinder_volume_snapshots.list() self.mock_tenant_list.return_value = [self.tenants.list(), False] - - res = self.client.get(parse.unquote(url)) + formData = {} + if search_opts: + search_key, search_value = search_opts.popitem() + formData['volume_backups__action_filter_admin_volume_backups'] \ + = search_value + formData['volume_backups__filter_admin_volume_backups__q_field'] \ + = search_key + else: + search_opts = {} + res = self.client.get(parse.unquote(url), formData) self.assertEqual(res.status_code, 200) self.assertTemplateUsed(res, 'horizon/common/_data_table_view.html') @@ -55,6 +64,7 @@ class AdminVolumeBackupsViewTests(test.BaseAdminViewTests): number_of_pages, res.context_data['view'].number_of_pages(None)) self.mock_volume_backup_list_paged_with_page_menu.\ assert_called_once_with(test.IsHttpRequest(), + search_opts=search_opts, page_number=page_number, all_tenants=True) self.mock_volume_list.assert_called_once_with( @@ -64,6 +74,51 @@ class AdminVolumeBackupsViewTests(test.BaseAdminViewTests): search_opts={'all_tenants': 1}) return res + @override_settings(API_RESULT_PAGE_SIZE=1) + def test_backups_index_paginated_with_filter(self): + size = settings.API_RESULT_PAGE_SIZE + base_url = INDEX_URL + page_number = 1 + + # get size filter + search_opts = {"size": 20} + backups = self.cinder_volume_backups.filter(**search_opts) + number_of_pages = len(backups) + expected_backups = backups[:size] + res = self._test_backups_index_paginated( + page_number=page_number, backups=expected_backups, url=base_url, + has_more=True, has_prev=False, page_size=size, + number_of_pages=number_of_pages, total_of_entries=number_of_pages, + search_opts=search_opts) + result = res.context['volume_backups_table'].data + self.assertCountEqual(result, expected_backups) + + # get status filter + search_opts = {"status": "available"} + backups = self.cinder_volume_backups.filter(**search_opts) + number_of_pages = len(backups) + expected_backups = backups[:size] + res = self._test_backups_index_paginated( + page_number=page_number, backups=expected_backups, url=base_url, + has_more=True, has_prev=False, page_size=size, + number_of_pages=number_of_pages, total_of_entries=number_of_pages, + search_opts=search_opts) + result = res.context['volume_backups_table'].data + self.assertCountEqual(result, expected_backups) + + # get name filter + search_opts = {"name": "backup2"} + backups = self.cinder_volume_backups.filter(**search_opts) + number_of_pages = len(backups) + expected_backups = backups[:size] + res = self._test_backups_index_paginated( + page_number=page_number, backups=expected_backups, url=base_url, + has_more=False, has_prev=False, page_size=size, + number_of_pages=number_of_pages, total_of_entries=number_of_pages, + search_opts=search_opts) + result = res.context['volume_backups_table'].data + self.assertCountEqual(result, expected_backups) + @override_settings(API_RESULT_PAGE_SIZE=1) def test_backups_index_paginated(self): backups = self.cinder_volume_backups.list() @@ -165,6 +220,7 @@ class AdminVolumeBackupsViewTests(test.BaseAdminViewTests): self.assertMessageCount(success=1) self.mock_volume_backup_list_paged_with_page_menu.\ assert_called_once_with(test.IsHttpRequest(), + search_opts={}, page_number=page_number, all_tenants=True) self.mock_volume_list.assert_called_once_with( diff --git a/openstack_dashboard/dashboards/admin/backups/views.py b/openstack_dashboard/dashboards/admin/backups/views.py index 4f0a1ddfc..815f02b0d 100644 --- a/openstack_dashboard/dashboards/admin/backups/views.py +++ b/openstack_dashboard/dashboards/admin/backups/views.py @@ -46,14 +46,23 @@ class AdminBackupsView(tables.PagedTableWithPageMenu, tables.DataTableView, return api.cinder.volume_backup_supported(self.request) def get_data(self): + filters = self.get_filters() + + # If the tenant filter selected and the tenant does not exist. + # We do not need to retrieve the list from cinder,just return + # an empty list. + if 'project_id' in filters and not filters['project_id']: + return [] + try: - search_opts = {'all_tenants': 1} self._current_page = self._get_page_number() (backups, self._page_size, self._total_of_entries, self._number_of_pages) = \ api.cinder.volume_backup_list_paged_with_page_menu( - self.request, page_number=self._current_page, - all_tenants=True) + self.request, search_opts=filters, + page_number=self._current_page, + all_tenants=True + ) except Exception as e: LOG.exception(e) backups = [] @@ -61,6 +70,8 @@ class AdminBackupsView(tables.PagedTableWithPageMenu, tables.DataTableView, "volume backups.")) if not backups: return backups + + search_opts = {'all_tenants': True} volumes = api.cinder.volume_list(self.request, search_opts=search_opts) volumes = dict((v.id, v) for v in volumes) snapshots = api.cinder.volume_snapshot_list(self.request, @@ -84,6 +95,22 @@ class AdminBackupsView(tables.PagedTableWithPageMenu, tables.DataTableView, backup.tenant_name = getattr(tenant, "name", None) return backups + def get_filters(self, filters=None, filters_map=None): + self.table = self._tables['volume_backups'] + self.handle_server_filter(self.request, table=self.table) + self.update_server_filter_action(self.request, table=self.table) + filters = super().get_filters(filters, filters_map) + if 'project' in filters: + tenants = api.keystone.tenant_list(self.request)[0] + tenant_filter_ids = [t.id for t in tenants + if t.name == filters['project']] + if tenant_filter_ids: + filters['project_id'] = tenant_filter_ids[0] + else: + filters['project_id'] = tenant_filter_ids + del filters['project'] + return filters + class UpdateStatusView(forms.ModalFormView): form_class = admin_forms.UpdateStatus diff --git a/openstack_dashboard/dashboards/project/backups/tables.py b/openstack_dashboard/dashboards/project/backups/tables.py index 4cbf34ef8..8abcadf6c 100644 --- a/openstack_dashboard/dashboards/project/backups/tables.py +++ b/openstack_dashboard/dashboards/project/backups/tables.py @@ -138,6 +138,14 @@ def get_size(backup): return _("%sGB") % backup.size +class BackupsFilterAction(tables.FilterAction): + + def filter(self, table, volumes, filter_string): + q = filter_string.lower() + return [volume for volume in volumes + if q in volume.name.lower()] + + class BackupsTable(tables.DataTable): STATUS_CHOICES = ( ("available", True), @@ -195,5 +203,5 @@ class BackupsTable(tables.DataTable): pagination_param = 'page' status_columns = ("status",) row_class = UpdateRow - table_actions = (DeleteBackup,) + table_actions = (DeleteBackup, BackupsFilterAction) row_actions = (RestoreBackup, DeleteBackup) -- cgit v1.2.1