From 732cb8ef4fd6c77bd5e27f049dbabc10fbf2514a Mon Sep 17 00:00:00 2001 From: Aashish Sharma Date: Thu, 20 Apr 2023 10:52:41 +0530 Subject: [PATCH] mgr/dashboard: Migrate from single site to multi-site Signed-off-by: Aashish Sharma --- src/pybind/mgr/dashboard/controllers/rgw.py | 18 ++ .../rgw-multisite-details.component.html | 10 +- .../rgw-multisite-details.component.ts | 38 +++- .../rgw-multisite-migrate.component.html | 137 ++++++++++++ .../rgw-multisite-migrate.component.scss | 0 .../rgw-multisite-migrate.component.spec.ts | 38 ++++ .../rgw-multisite-migrate.component.ts | 202 ++++++++++++++++++ .../rgw-multisite-zone-form.component.ts | 4 +- .../frontend/src/app/ceph/rgw/rgw.module.ts | 4 +- .../app/shared/api/rgw-multisite.service.ts | 15 ++ .../src/app/shared/constants/app.constants.ts | 3 + .../mgr/dashboard/services/rgw_client.py | 85 ++++++++ 12 files changed, 549 insertions(+), 5 deletions(-) create mode 100644 src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-multisite-migrate/rgw-multisite-migrate.component.html create mode 100644 src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-multisite-migrate/rgw-multisite-migrate.component.scss create mode 100644 src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-multisite-migrate/rgw-multisite-migrate.component.spec.ts create mode 100644 src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-multisite-migrate/rgw-multisite-migrate.component.ts diff --git a/src/pybind/mgr/dashboard/controllers/rgw.py b/src/pybind/mgr/dashboard/controllers/rgw.py index 37e058664c565..a28f1d98a4f6a 100644 --- a/src/pybind/mgr/dashboard/controllers/rgw.py +++ b/src/pybind/mgr/dashboard/controllers/rgw.py @@ -12,6 +12,7 @@ from ..rest_client import RequestException from ..security import Permission, Scope from ..services.auth import AuthManager, JwtManager from ..services.ceph_service import CephService +from ..services.orchestrator import OrchClient from ..services.rgw_client import NoRgwDaemonsException, RgwClient from ..tools import json_str_to_object, str_to_bool from . import APIDoc, APIRouter, BaseController, CreatePermission, \ @@ -108,6 +109,23 @@ class RgwStatus(BaseController): raise DashboardException(e, http_status_code=404, component='rgw') # noqa: E501 pylint: disable=line-too-long return result + @Endpoint(method='PUT') + # pylint: disable=W0102 + def migrate(self, realm_name=None, zonegroup_name=None, zone_name=None, + zonegroup_endpoints: List[str] = [], zone_endpoints: List[str] = [], + user=None, daemon_name: Optional[str] = None): + try: + instance = RgwClient.admin_instance(daemon_name=daemon_name) + result = instance.migrate_to_multisite(realm_name, zonegroup_name, zone_name, + zonegroup_endpoints, zone_endpoints, user) + orch = OrchClient.instance() + daemons = orch.services.list_daemons(service_name='rgw') + for daemon in daemons: + orch.daemons.action(action='reload', daemon_name=daemon.daemon_id) + except NoRgwDaemonsException as e: + raise DashboardException(e, http_status_code=404, component='rgw') + return result + @APIRouter('/rgw/daemon', Scope.RGW) @APIDoc("RGW Daemon Management API", "RgwDaemon") diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-multisite-details/rgw-multisite-details.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-multisite-details/rgw-multisite-details.component.html index 3c65390a177e9..ae5b01df64b12 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-multisite-details/rgw-multisite-details.component.html +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-multisite-details/rgw-multisite-details.component.html @@ -1,11 +1,19 @@
- + + + +
this.openModal('zone') }; + const migrateMultsiteAction: CdTableAction = { + permission: 'read', + icon: Icons.exchange, + name: this.actionLabels.MIGRATE, + click: () => this.openMigrateModal() + }; this.createTableActions = [createRealmAction, createZonegroupAction, createZoneAction]; + this.migrateTableAction = [migrateMultsiteAction]; } openModal(entity: any, edit = false) { @@ -137,6 +148,15 @@ export class RgwMultisiteDetailsComponent implements OnDestroy, OnInit { } } + openMigrateModal() { + const initialState = { + multisiteInfo: this.multisiteInfo + }; + this.bsModalRef = this.modalService.show(RgwMultisiteMigrateComponent, initialState, { + size: 'lg' + }); + } + ngOnInit() { const observables = [ this.rgwRealmService.getAllRealmsInfo(), @@ -257,6 +277,7 @@ export class RgwMultisiteDetailsComponent implements OnDestroy, OnInit { } this.realmIds = []; this.zoneIds = []; + this.getDisableMigrate(); return allNodes; } @@ -312,6 +333,21 @@ export class RgwMultisiteDetailsComponent implements OnDestroy, OnInit { } } + getDisableMigrate() { + if ( + this.realms.length === 0 && + this.zonegroups.length === 1 && + this.zonegroups[0].name === 'default' && + this.zones.length === 1 && + this.zones[0].name === 'default' + ) { + this.showMigrateAction = true; + } else { + this.showMigrateAction = false; + } + return this.showMigrateAction; + } + delete(node: TreeNode) { if (node.data.type === 'realm') { this.modalRef = this.modalService.show(CriticalConfirmationModalComponent, { diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-multisite-migrate/rgw-multisite-migrate.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-multisite-migrate/rgw-multisite-migrate.component.html new file mode 100644 index 0000000000000..ceb0afc5d57bf --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-multisite-migrate/rgw-multisite-migrate.component.html @@ -0,0 +1,137 @@ + + Migrate Single Site to Multi-site + + Migrate from a single-site deployment with a default zonegroup and zone to a multi-site system + + + + +
+ + +
+
+
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-multisite-migrate/rgw-multisite-migrate.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-multisite-migrate/rgw-multisite-migrate.component.scss new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-multisite-migrate/rgw-multisite-migrate.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-multisite-migrate/rgw-multisite-migrate.component.spec.ts new file mode 100644 index 0000000000000..77d924d1a4480 --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-multisite-migrate/rgw-multisite-migrate.component.spec.ts @@ -0,0 +1,38 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { RgwMultisiteMigrateComponent } from './rgw-multisite-migrate.component'; +import { HttpClientTestingModule } from '@angular/common/http/testing'; +import { ReactiveFormsModule } from '@angular/forms'; +import { RouterTestingModule } from '@angular/router/testing'; +import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; +import { ToastrModule } from 'ngx-toastr'; +import { SharedModule } from '~/app/shared/shared.module'; + +describe('RgwMultisiteMigrateComponent', () => { + let component: RgwMultisiteMigrateComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [ + SharedModule, + ReactiveFormsModule, + RouterTestingModule, + HttpClientTestingModule, + ToastrModule.forRoot() + ], + declarations: [RgwMultisiteMigrateComponent], + providers: [NgbActiveModal] + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(RgwMultisiteMigrateComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-multisite-migrate/rgw-multisite-migrate.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-multisite-migrate/rgw-multisite-migrate.component.ts new file mode 100644 index 0000000000000..786a30fc119b4 --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-multisite-migrate/rgw-multisite-migrate.component.ts @@ -0,0 +1,202 @@ +import { Component, EventEmitter, OnInit, Output } from '@angular/core'; +import { FormControl, Validators } from '@angular/forms'; +import { NgbActiveModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap'; +import _ from 'lodash'; +import { RgwMultisiteService } from '~/app/shared/api/rgw-multisite.service'; +import { RgwRealmService } from '~/app/shared/api/rgw-realm.service'; +import { RgwZoneService } from '~/app/shared/api/rgw-zone.service'; +import { RgwZonegroupService } from '~/app/shared/api/rgw-zonegroup.service'; +import { ActionLabelsI18n } from '~/app/shared/constants/app.constants'; +import { NotificationType } from '~/app/shared/enum/notification-type.enum'; +import { CdFormGroup } from '~/app/shared/forms/cd-form-group'; +import { CdValidators } from '~/app/shared/forms/cd-validators'; +import { NotificationService } from '~/app/shared/services/notification.service'; +import { RgwRealm, RgwZone, RgwZonegroup } from '../models/rgw-multisite'; +import { ModalService } from '~/app/shared/services/modal.service'; + +@Component({ + selector: 'cd-rgw-multisite-migrate', + templateUrl: './rgw-multisite-migrate.component.html', + styleUrls: ['./rgw-multisite-migrate.component.scss'] +}) +export class RgwMultisiteMigrateComponent implements OnInit { + readonly endpoints = /^((https?:\/\/)|(www.))(?:([a-zA-Z]+)|(\d+\.\d+.\d+.\d+)):\d{2,4}$/; + readonly ipv4Rgx = /^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/i; + readonly ipv6Rgx = /^(?:[a-f0-9]{1,4}:){7}[a-f0-9]{1,4}$/i; + + @Output() + submitAction = new EventEmitter(); + + multisiteMigrateForm: CdFormGroup; + zoneNames: string[]; + realmList: RgwRealm[]; + multisiteInfo: object[] = []; + realmNames: string[]; + zonegroupList: RgwZonegroup[]; + zonegroupNames: string[]; + zoneList: RgwZone[]; + realm: RgwRealm; + zonegroup: RgwZonegroup; + zone: RgwZone; + newZonegroupName: any; + newZoneName: any; + bsModalRef: NgbModalRef; + users: any; + + constructor( + public activeModal: NgbActiveModal, + public actionLabels: ActionLabelsI18n, + public rgwMultisiteService: RgwMultisiteService, + public rgwZoneService: RgwZoneService, + public notificationService: NotificationService, + public rgwZonegroupService: RgwZonegroupService, + public rgwRealmService: RgwRealmService, + public modalService: ModalService + ) { + this.createForm(); + } + + createForm() { + this.multisiteMigrateForm = new CdFormGroup({ + realmName: new FormControl(null, { + validators: [ + Validators.required, + CdValidators.custom('uniqueName', (realmName: string) => { + return this.realmNames && this.zoneNames.indexOf(realmName) !== -1; + }) + ] + }), + zonegroupName: new FormControl(null, { + validators: [ + Validators.required, + CdValidators.custom('uniqueName', (zonegroupName: string) => { + return this.zonegroupNames && this.zoneNames.indexOf(zonegroupName) !== -1; + }) + ] + }), + zoneName: new FormControl(null, { + validators: [ + Validators.required, + CdValidators.custom('uniqueName', (zoneName: string) => { + return this.zoneNames && this.zoneNames.indexOf(zoneName) !== -1; + }) + ] + }), + zone_endpoints: new FormControl([], { + validators: [ + CdValidators.custom('endpoint', (value: string) => { + if (_.isEmpty(value)) { + return false; + } else { + if (value.includes(',')) { + value.split(',').forEach((url: string) => { + return ( + !this.endpoints.test(url) && !this.ipv4Rgx.test(url) && !this.ipv6Rgx.test(url) + ); + }); + } else { + return ( + !this.endpoints.test(value) && + !this.ipv4Rgx.test(value) && + !this.ipv6Rgx.test(value) + ); + } + return false; + } + }), + Validators.required + ] + }), + zonegroup_endpoints: new FormControl( + [], + [ + CdValidators.custom('endpoint', (value: string) => { + if (_.isEmpty(value)) { + return false; + } else { + if (value.includes(',')) { + value.split(',').forEach((url: string) => { + return ( + !this.endpoints.test(url) && !this.ipv4Rgx.test(url) && !this.ipv6Rgx.test(url) + ); + }); + } else { + return ( + !this.endpoints.test(value) && + !this.ipv4Rgx.test(value) && + !this.ipv6Rgx.test(value) + ); + } + return false; + } + }), + Validators.required + ] + ), + users: new FormControl(null) + }); + } + + ngOnInit(): void { + this.realmList = + this.multisiteInfo[0] !== undefined && this.multisiteInfo[0].hasOwnProperty('realms') + ? this.multisiteInfo[0]['realms'] + : []; + this.realmNames = this.realmList.map((realm) => { + return realm['name']; + }); + this.zonegroupList = + this.multisiteInfo[1] !== undefined && this.multisiteInfo[1].hasOwnProperty('zonegroups') + ? this.multisiteInfo[1]['zonegroups'] + : []; + this.zonegroupNames = this.zonegroupList.map((zonegroup) => { + return zonegroup['name']; + }); + this.zoneList = + this.multisiteInfo[2] !== undefined && this.multisiteInfo[2].hasOwnProperty('zones') + ? this.multisiteInfo[2]['zones'] + : []; + this.zoneNames = this.zoneList.map((zone) => { + return zone['name']; + }); + this.rgwZoneService.getUserList('default').subscribe((users: any) => { + this.users = users.filter((user: any) => user['system'] === true); + }); + } + + submit() { + const values = this.multisiteMigrateForm.value; + this.realm = new RgwRealm(); + this.realm.name = values['realmName']; + this.zonegroup = new RgwZonegroup(); + this.zonegroup.name = values['zonegroupName']; + this.zonegroup.endpoints = this.checkUrlArray(values['zonegroup_endpoints']); + this.zone = new RgwZone(); + this.zone.name = values['zoneName']; + this.zone.endpoints = this.checkUrlArray(values['zone_endpoints']); + const user = values['users']; + this.rgwMultisiteService.migrate(this.realm, this.zonegroup, this.zone, user).subscribe( + () => { + this.notificationService.show( + NotificationType.success, + $localize`${this.actionLabels.MIGRATE} done successfully` + ); + this.submitAction.emit(); + this.activeModal.close(); + }, + () => { + this.notificationService.show(NotificationType.error, $localize`Migration failed`); + } + ); + } + + checkUrlArray(endpoints: string) { + let endpointsArray = []; + if (endpoints.includes(',')) { + endpointsArray = endpoints.split(','); + } else { + endpointsArray.push(endpoints); + } + return endpointsArray; + } +} diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-multisite-zone-form/rgw-multisite-zone-form.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-multisite-zone-form/rgw-multisite-zone-form.component.ts index 7a0c7ecb9835b..1fe980e4cd5b0 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-multisite-zone-form/rgw-multisite-zone-form.component.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-multisite-zone-form/rgw-multisite-zone-form.component.ts @@ -211,7 +211,7 @@ export class RgwMultisiteZoneFormComponent implements OnInit { this.onZoneGroupChange(this.info.data.parent); setTimeout(() => { this.getUserInfo(zone); - }, 1500); + }, 1000); } if ( this.multisiteZoneForm.getValue('selectedZonegroup') !== @@ -330,7 +330,7 @@ export class RgwMultisiteZoneFormComponent implements OnInit { this.zone.name = this.info.data.name; this.zone.endpoints = values['zone_endpoints'] === this.info.data.endpoints - ? values['zonegroup_endpoints'] + ? values['zone_endpoints'] : this.checkUrlArray(values['zone_endpoints']); this.rgwZoneService .update( diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw.module.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw.module.ts index 31c5d9d8cfda4..696df2b639c64 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw.module.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw.module.ts @@ -37,6 +37,7 @@ import { CrudFormComponent } from '~/app/shared/forms/crud-form/crud-form.compon import { RgwMultisiteZoneDeletionFormComponent } from './models/rgw-multisite-zone-deletion-form/rgw-multisite-zone-deletion-form.component'; import { RgwMultisiteZonegroupDeletionFormComponent } from './models/rgw-multisite-zonegroup-deletion-form/rgw-multisite-zonegroup-deletion-form.component'; import { RgwSystemUserComponent } from './rgw-system-user/rgw-system-user.component'; +import { RgwMultisiteMigrateComponent } from './rgw-multisite-migrate/rgw-multisite-migrate.component'; @NgModule({ imports: [ @@ -83,7 +84,8 @@ import { RgwSystemUserComponent } from './rgw-system-user/rgw-system-user.compon RgwMultisiteZoneFormComponent, RgwMultisiteZoneDeletionFormComponent, RgwMultisiteZonegroupDeletionFormComponent, - RgwSystemUserComponent + RgwSystemUserComponent, + RgwMultisiteMigrateComponent ] }) export class RgwModule {} diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/api/rgw-multisite.service.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/rgw-multisite.service.ts index 400a273cb039a..0a601bf0fa13c 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/shared/api/rgw-multisite.service.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/rgw-multisite.service.ts @@ -1,6 +1,7 @@ import { HttpClient } from '@angular/common/http'; import { Injectable } from '@angular/core'; import { RgwDaemonService } from './rgw-daemon.service'; +import { RgwRealm, RgwZone, RgwZonegroup } from '~/app/ceph/rgw/models/rgw-multisite'; @Injectable({ providedIn: 'root' @@ -15,4 +16,18 @@ export class RgwMultisiteService { return this.http.get(`${this.url}/sync_status`); }); } + + migrate(realm: RgwRealm, zonegroup: RgwZonegroup, zone: RgwZone, user: string) { + return this.rgwDaemonService.request((requestBody: any) => { + requestBody = { + realm_name: realm.name, + zonegroup_name: zonegroup.name, + zone_name: zone.name, + zonegroup_endpoints: zonegroup.endpoints, + zone_endpoints: zone.endpoints, + user: user + }; + return this.http.put(`${this.url}/migrate`, requestBody); + }); + } } diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/constants/app.constants.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/constants/app.constants.ts index cdc81d6d1ed74..aec37abad607d 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/shared/constants/app.constants.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/constants/app.constants.ts @@ -139,6 +139,7 @@ export class ActionLabelsI18n { RESYNC: string; EXPORT: string; IMPORT: any; + MIGRATE: string; constructor() { /* Create a new item */ @@ -148,6 +149,8 @@ export class ActionLabelsI18n { this.IMPORT = $localize`Import`; + this.MIGRATE = $localize`Migrate to Multi-Site`; + /* Destroy an existing item */ this.DELETE = $localize`Delete`; diff --git a/src/pybind/mgr/dashboard/services/rgw_client.py b/src/pybind/mgr/dashboard/services/rgw_client.py index ee7652187093a..4a70f67310837 100644 --- a/src/pybind/mgr/dashboard/services/rgw_client.py +++ b/src/pybind/mgr/dashboard/services/rgw_client.py @@ -1260,6 +1260,91 @@ class RgwClient(RestClient): raise DashboardException(error, http_status_code=500, component='rgw') return all_users_info + def migrate_to_multisite(self, realm_name: str, zonegroup_name: str, zone_name: str, + zonegroup_endpoints: List[str], zone_endpoints: List[str], user: str): + rgw_realm_create_cmd = ['realm', 'create', '--rgw-realm', realm_name, '--default'] + try: + exit_code, _, err = mgr.send_rgwadmin_command(rgw_realm_create_cmd, False) + if exit_code > 0: + raise DashboardException(e=err, msg='Unable to create realm', + http_status_code=500, component='rgw') + except SubprocessError as error: + raise DashboardException(error, http_status_code=500, component='rgw') + + rgw_zonegroup_edit_cmd = ['zonegroup', 'rename', '--rgw-zonegroup', 'default', + '--zonegroup-new-name', zonegroup_name] + try: + exit_code, _, err = mgr.send_rgwadmin_command(rgw_zonegroup_edit_cmd, False) + if exit_code > 0: + raise DashboardException(e=err, msg='Unable to rename zonegroup to {}'.format(zonegroup_name), # noqa E501 #pylint: disable=line-too-long + http_status_code=500, component='rgw') + except SubprocessError as error: + raise DashboardException(error, http_status_code=500, component='rgw') + + rgw_zone_edit_cmd = ['zone', 'rename', '--rgw-zone', + 'default', '--zone-new-name', zone_name, + '--rgw-zonegroup', zonegroup_name] + try: + exit_code, _, err = mgr.send_rgwadmin_command(rgw_zone_edit_cmd, False) + if exit_code > 0: + raise DashboardException(e=err, msg='Unable to rename zone to {}'.format(zone_name), # noqa E501 #pylint: disable=line-too-long + http_status_code=500, component='rgw') + except SubprocessError as error: + raise DashboardException(error, http_status_code=500, component='rgw') + + rgw_zonegroup_modify_cmd = ['zonegroup', 'modify', + '--rgw-realm', realm_name, + '--rgw-zonegroup', zonegroup_name] + if zonegroup_endpoints: + if len(zonegroup_endpoints) > 1: + endpoint = ','.join(str(e) for e in zonegroup_endpoints) + else: + endpoint = zonegroup_endpoints[0] + rgw_zonegroup_modify_cmd.append('--endpoints') + rgw_zonegroup_modify_cmd.append(endpoint) + rgw_zonegroup_modify_cmd.append('--master') + rgw_zonegroup_modify_cmd.append('--default') + try: + exit_code, _, err = mgr.send_rgwadmin_command(rgw_zonegroup_modify_cmd) + if exit_code > 0: + raise DashboardException(e=err, msg='Unable to modify zonegroup {}'.format(zonegroup_name), # noqa E501 #pylint: disable=line-too-long + http_status_code=500, component='rgw') + except SubprocessError as error: + raise DashboardException(error, http_status_code=500, component='rgw') + + rgw_zone_modify_cmd = ['zone', 'modify', '--rgw-realm', realm_name, + '--rgw-zonegroup', zonegroup_name, + '--rgw-zone', zone_name] + if zone_endpoints: + if len(zone_endpoints) > 1: + endpoint = ','.join(str(e) for e in zone_endpoints) + else: + endpoint = zone_endpoints[0] + rgw_zone_modify_cmd.append('--endpoints') + rgw_zone_modify_cmd.append(endpoint) + rgw_zone_modify_cmd.append('--master') + rgw_zone_modify_cmd.append('--default') + try: + exit_code, _, err = mgr.send_rgwadmin_command(rgw_zone_modify_cmd) + if exit_code > 0: + raise DashboardException(e=err, msg='Unable to modify zone', + http_status_code=500, component='rgw') + except SubprocessError as error: + raise DashboardException(error, http_status_code=500, component='rgw') + + if user: + access_key, secret_key = self.get_rgw_user_keys(user, zone_name) + rgw_zone_modify_cmd = ['zone', 'modify', '--rgw-zone', zone_name, + '--access-key', access_key, '--secret', secret_key] + try: + exit_code, _, err = mgr.send_rgwadmin_command(rgw_zone_modify_cmd) + if exit_code > 0: + raise DashboardException(e=err, msg='Unable to modify zone', + http_status_code=500, component='rgw') + except SubprocessError as error: + raise DashboardException(error, http_status_code=500, component='rgw') + self.update_period() + @RestClient.api_get('/{bucket_name}?versioning') def get_bucket_versioning(self, bucket_name, request=None): """ -- 2.39.5