From 52278f169fe94136c474a1758d4d0048e65edb50 Mon Sep 17 00:00:00 2001 From: Naman Munet Date: Thu, 12 Sep 2024 17:29:22 +0530 Subject: [PATCH] mgr/dashboard: zonegroup level policy created at master zone did not sync to non-master zone added period update for zonegroup level changes so as to sync them Fixes: https://tracker.ceph.com/issues/68049 Signed-off-by: Naman Munet --- src/pybind/mgr/dashboard/controllers/rgw.py | 14 ++++---- .../cypress/e2e/rgw/multisite.e2e-spec.ts | 16 +++++++-- .../frontend/cypress/e2e/rgw/multisite.po.ts | 9 ++--- .../mgr/dashboard/services/rgw_client.py | 34 +++++++++++++++---- 4 files changed, 52 insertions(+), 21 deletions(-) diff --git a/src/pybind/mgr/dashboard/controllers/rgw.py b/src/pybind/mgr/dashboard/controllers/rgw.py index a1dab1cab110e..398fa341bf278 100755 --- a/src/pybind/mgr/dashboard/controllers/rgw.py +++ b/src/pybind/mgr/dashboard/controllers/rgw.py @@ -180,21 +180,21 @@ class RgwMultisiteController(RESTController): @CreatePermission def create_sync_policy_group(self, group_id: str, status: str, bucket_name=''): multisite_instance = RgwMultisite() - return multisite_instance.create_sync_policy_group(group_id, status, bucket_name) + return multisite_instance.create_sync_policy_group(group_id, status, bucket_name, True) @Endpoint(method='PUT', path='/sync-policy-group') @EndpointDoc("Update the sync policy group") @UpdatePermission def update_sync_policy_group(self, group_id: str, status: str, bucket_name=''): multisite_instance = RgwMultisite() - return multisite_instance.update_sync_policy_group(group_id, status, bucket_name) + return multisite_instance.update_sync_policy_group(group_id, status, bucket_name, True) @Endpoint(method='DELETE', path='/sync-policy-group') @EndpointDoc("Remove the sync policy group") @DeletePermission def remove_sync_policy_group(self, group_id: str, bucket_name=''): multisite_instance = RgwMultisite() - return multisite_instance.remove_sync_policy_group(group_id, bucket_name) + return multisite_instance.remove_sync_policy_group(group_id, bucket_name, True) @Endpoint(method='PUT', path='/sync-flow') @EndpointDoc("Create or update the sync flow") @@ -206,7 +206,7 @@ class RgwMultisiteController(RESTController): bucket_name=''): multisite_instance = RgwMultisite() return multisite_instance.create_sync_flow(group_id, flow_id, flow_type, zones, - bucket_name, source_zone, destination_zone) + bucket_name, source_zone, destination_zone, True) @Endpoint(method='DELETE', path='/sync-flow') @EndpointDoc("Remove the sync flow") @@ -216,7 +216,7 @@ class RgwMultisiteController(RESTController): bucket_name=''): multisite_instance = RgwMultisite() return multisite_instance.remove_sync_flow(group_id, flow_id, flow_type, source_zone, - destination_zone, zones, bucket_name) + destination_zone, zones, bucket_name, True) @Endpoint(method='PUT', path='/sync-pipe') @EndpointDoc("Create or update the sync pipe") @@ -229,7 +229,7 @@ class RgwMultisiteController(RESTController): multisite_instance = RgwMultisite() return multisite_instance.create_sync_pipe(group_id, pipe_id, source_zones, destination_zones, source_bucket, - destination_bucket, bucket_name) + destination_bucket, bucket_name, True) @Endpoint(method='DELETE', path='/sync-pipe') @EndpointDoc("Remove the sync pipe") @@ -242,7 +242,7 @@ class RgwMultisiteController(RESTController): multisite_instance = RgwMultisite() return multisite_instance.remove_sync_pipe(group_id, pipe_id, source_zones, destination_zones, destination_bucket, - bucket_name) + bucket_name, True) @APIRouter('/rgw/daemon', Scope.RGW) diff --git a/src/pybind/mgr/dashboard/frontend/cypress/e2e/rgw/multisite.e2e-spec.ts b/src/pybind/mgr/dashboard/frontend/cypress/e2e/rgw/multisite.e2e-spec.ts index 6a02c7e10c90a..8d8ed22da0b7f 100644 --- a/src/pybind/mgr/dashboard/frontend/cypress/e2e/rgw/multisite.e2e-spec.ts +++ b/src/pybind/mgr/dashboard/frontend/cypress/e2e/rgw/multisite.e2e-spec.ts @@ -1,7 +1,17 @@ +import { BucketsPageHelper } from './buckets.po'; import { MultisitePageHelper } from './multisite.po'; describe('Multisite page', () => { const multisite = new MultisitePageHelper(); + const buckets = new BucketsPageHelper(); + const bucket_name = 'e2ebucket'; + + before(() => { + cy.login(); + buckets.navigateTo('create'); + buckets.create(bucket_name, BucketsPageHelper.USERS[0]); + buckets.getFirstTableCell(bucket_name).should('exist'); + }); beforeEach(() => { cy.login(); @@ -17,13 +27,13 @@ describe('Multisite page', () => { describe('create, edit & delete sync group policy', () => { it('should create policy', () => { multisite.navigateTo('create'); - multisite.create('test', 'Enabled'); + multisite.create('test', 'Enabled', bucket_name); multisite.getFirstTableCell('test').should('exist'); }); it('should edit policy status', () => { multisite.navigateTo(); - multisite.edit('test', 'Forbidden'); + multisite.edit('test', 'Forbidden', bucket_name); }); it('should delete policy', () => { @@ -36,7 +46,7 @@ describe('Multisite page', () => { describe.skip('create, edit & delete symmetrical sync Flow', () => { it('Preparing...(creating sync group policy)', () => { multisite.navigateTo('create'); - multisite.create('test', 'Enabled'); + multisite.create('test', 'Enabled', bucket_name); multisite.getFirstTableCell('test').should('exist'); }); describe('symmetrical Flow creation started', () => { diff --git a/src/pybind/mgr/dashboard/frontend/cypress/e2e/rgw/multisite.po.ts b/src/pybind/mgr/dashboard/frontend/cypress/e2e/rgw/multisite.po.ts index 6a8bd3ef1e48b..0f2078f20bba4 100644 --- a/src/pybind/mgr/dashboard/frontend/cypress/e2e/rgw/multisite.po.ts +++ b/src/pybind/mgr/dashboard/frontend/cypress/e2e/rgw/multisite.po.ts @@ -22,21 +22,22 @@ export class MultisitePageHelper extends PageHelper { } @PageHelper.restrictTo(pages.create.url) - create(group_id: string, status: string) { + create(group_id: string, status: string, bucket_name: string) { // Enter in group_id cy.get('#group_id').type(group_id); // Show Status this.selectOption('status', status); cy.get('#status').should('have.class', 'ng-valid'); - + // Enter the bucket_name + cy.get('#bucket_name').type(bucket_name); // Click the create button and wait for policy to be made cy.contains('button', 'Create Sync Policy Group').wait(WAIT_TIMER).click(); this.getFirstTableCell(group_id).should('exist'); } @PageHelper.restrictTo(pages.index.url) - edit(group_id: string, status: string) { - cy.visit(`${pages.edit.url}/${group_id})`); + edit(group_id: string, status: string, bucket_name: string) { + cy.visit(`${pages.edit.url}/${group_id}/${bucket_name})`); // Change the status field this.selectOption('status', status); diff --git a/src/pybind/mgr/dashboard/services/rgw_client.py b/src/pybind/mgr/dashboard/services/rgw_client.py index 1f9fa74f4256f..081e41650722e 100755 --- a/src/pybind/mgr/dashboard/services/rgw_client.py +++ b/src/pybind/mgr/dashboard/services/rgw_client.py @@ -2032,7 +2032,8 @@ class RgwMultisite: except SubprocessError as error: raise DashboardException(error, http_status_code=500, component='rgw') - def create_sync_policy_group(self, group_id: str, status: str, bucket_name: str = ''): + def create_sync_policy_group(self, group_id: str, status: str, bucket_name: str = '', + update_period=False): rgw_sync_policy_cmd = ['sync', 'group', 'create', '--group-id', group_id, '--status', SyncStatus[status].value] if bucket_name: @@ -2044,8 +2045,11 @@ class RgwMultisite: http_status_code=500, component='rgw') except SubprocessError as error: raise DashboardException(error, http_status_code=500, component='rgw') + if not bucket_name and update_period: + self.update_period() - def update_sync_policy_group(self, group_id: str, status: str, bucket_name: str = ''): + def update_sync_policy_group(self, group_id: str, status: str, bucket_name: str = '', + update_period=False): rgw_sync_policy_cmd = ['sync', 'group', 'modify', '--group-id', group_id, '--status', SyncStatus[status].value] if bucket_name: @@ -2057,8 +2061,10 @@ class RgwMultisite: http_status_code=500, component='rgw') except SubprocessError as error: raise DashboardException(error, http_status_code=500, component='rgw') + if not bucket_name and update_period: + self.update_period() - def remove_sync_policy_group(self, group_id: str, bucket_name=''): + def remove_sync_policy_group(self, group_id: str, bucket_name='', update_period=False): rgw_sync_policy_cmd = ['sync', 'group', 'remove', '--group-id', group_id] if bucket_name: rgw_sync_policy_cmd += ['--bucket', bucket_name] @@ -2069,11 +2075,14 @@ class RgwMultisite: http_status_code=500, component='rgw') except SubprocessError as error: raise DashboardException(error, http_status_code=500, component='rgw') + if not bucket_name and update_period: + self.update_period() def create_sync_flow(self, group_id: str, flow_id: str, flow_type: str, zones: Optional[Dict[str, List]] = None, bucket_name: str = '', source_zone: Optional[str] = None, - destination_zone: Optional[str] = None): + destination_zone: Optional[str] = None, + update_period=False): rgw_sync_policy_cmd = ['sync', 'group', 'flow', 'create', '--group-id', group_id, '--flow-id', flow_id, '--flow-type', SyncFlowTypes[flow_type].value] @@ -2114,10 +2123,13 @@ class RgwMultisite: if len(zones['removed']) > 0: self.remove_sync_flow(group_id, flow_id, flow_type, source_zone, destination_zone, zones['removed'], bucket_name) + if not bucket_name and update_period: + self.update_period() def remove_sync_flow(self, group_id: str, flow_id: str, flow_type: str, source_zone='', destination_zone='', - zones: Optional[List[str]] = None, bucket_name: str = ''): + zones: Optional[List[str]] = None, bucket_name: str = '', + update_period=False): rgw_sync_policy_cmd = ['sync', 'group', 'flow', 'remove', '--group-id', group_id, '--flow-id', flow_id, '--flow-type', SyncFlowTypes[flow_type].value] @@ -2138,13 +2150,16 @@ class RgwMultisite: http_status_code=500, component='rgw') except SubprocessError as error: raise DashboardException(error, http_status_code=500, component='rgw') + if not bucket_name and update_period: + self.update_period() def create_sync_pipe(self, group_id: str, pipe_id: str, source_zones: Dict[str, Any], destination_zones: Dict[str, Any], source_bucket: str = '', destination_bucket: str = '', - bucket_name: str = ''): + bucket_name: str = '', + update_period=False): if source_zones['added'] or destination_zones['added']: rgw_sync_policy_cmd = ['sync', 'group', 'pipe', 'create', @@ -2173,6 +2188,8 @@ class RgwMultisite: http_status_code=500, component='rgw') except SubprocessError as error: raise DashboardException(error, http_status_code=500, component='rgw') + if not bucket_name and update_period: + self.update_period() if source_zones['removed'] or destination_zones['removed']: self.remove_sync_pipe(group_id, pipe_id, source_zones['removed'], @@ -2182,7 +2199,8 @@ class RgwMultisite: def remove_sync_pipe(self, group_id: str, pipe_id: str, source_zones: Optional[List[str]] = None, destination_zones: Optional[List[str]] = None, - destination_bucket: str = '', bucket_name: str = ''): + destination_bucket: str = '', bucket_name: str = '', + update_period=False): rgw_sync_policy_cmd = ['sync', 'group', 'pipe', 'remove', '--group-id', group_id, '--pipe-id', pipe_id] @@ -2206,6 +2224,8 @@ class RgwMultisite: http_status_code=500, component='rgw') except SubprocessError as error: raise DashboardException(error, http_status_code=500, component='rgw') + if not bucket_name and update_period: + self.update_period() def create_dashboard_admin_sync_group(self, zonegroup_name: str = ''): -- 2.39.5