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, \
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")
<div class="row">
<div class="col-sm-12 col-lg-12">
<div>
- <cd-table-actions class="btn-group mb-4"
+ <cd-table-actions class="btn-group mb-4 me-2"
[permission]="permission"
[selection]="selection"
[tableActions]="createTableActions">
</cd-table-actions>
+ <span *ngIf="showMigrateAction">
+ <cd-table-actions class="btn-group mb-4 me-2 secondary"
+ [permission]="permission"
+ [btnColor]="'light'"
+ [selection]="selection"
+ [tableActions]="migrateTableAction">
+ </cd-table-actions>
+ </span>
</div>
<div class="card">
<div class="card-header"
import { NotificationService } from '~/app/shared/services/notification.service';
import { TimerService } from '~/app/shared/services/timer.service';
import { RgwRealm, RgwZone, RgwZonegroup } from '../models/rgw-multisite';
+import { RgwMultisiteMigrateComponent } from '../rgw-multisite-migrate/rgw-multisite-migrate.component';
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 { RgwMultisiteRealmFormComponent } from '../rgw-multisite-realm-form/rgw-multisite-realm-form.component';
messages = {
noDefaultRealm: $localize`Please create a default realm first to enable this feature`,
- noMasterZone: $localize`Please create a master zone for each zonegroups to enable this feature`
+ noMasterZone: $localize`Please create a master zone for each zonegroup to enable this feature`,
+ disableMigrate: $localize`Deployment is already migrated to multi-site system.`
};
icons = Icons;
permission: Permission;
selection = new CdTableSelection();
createTableActions: CdTableAction[];
+ migrateTableAction: CdTableAction[];
loadingIndicator = true;
nodes: object[] = [];
treeOptions: ITreeOptions = {
multisiteInfo: object[] = [];
defaultsInfo: string[] = [];
title: string = 'Edit';
+ showMigrateAction: boolean = false;
constructor(
private modalService: ModalService,
name: this.actionLabels.CREATE + ' Zone',
click: () => 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) {
}
}
+ openMigrateModal() {
+ const initialState = {
+ multisiteInfo: this.multisiteInfo
+ };
+ this.bsModalRef = this.modalService.show(RgwMultisiteMigrateComponent, initialState, {
+ size: 'lg'
+ });
+ }
+
ngOnInit() {
const observables = [
this.rgwRealmService.getAllRealmsInfo(),
}
this.realmIds = [];
this.zoneIds = [];
+ this.getDisableMigrate();
return allNodes;
}
}
}
+ 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, {
--- /dev/null
+<cd-modal [modalRef]="activeModal">
+ <ng-container i18n="form title"
+ class="modal-title">Migrate Single Site to Multi-site
+ <cd-helper>
+ <span>Migrate from a single-site deployment with a default zonegroup and zone to a multi-site system</span>
+ </cd-helper>
+ </ng-container>
+
+ <ng-container class="modal-content">
+ <form name="multisiteMigrateForm"
+ #formDir="ngForm"
+ [formGroup]="multisiteMigrateForm"
+ novalidate>
+ <div class="modal-body">
+ <div class="form-group row">
+ <label class="cd-col-form-label required"
+ for="realmName"
+ i18n>Realm Name</label>
+ <div class="cd-col-form-input">
+ <input class="form-control"
+ type="text"
+ placeholder="Realm name..."
+ id="realmName"
+ name="realmName"
+ formControlName="realmName">
+ <span class="invalid-feedback"
+ *ngIf="multisiteMigrateForm.showError('realmName', formDir, 'required')"
+ i18n>This field is required.</span>
+ <span class="invalid-feedback"
+ *ngIf="multisiteMigrateForm.showError('realmName', formDir, 'uniqueName')"
+ i18n>The chosen realm name is already in use.</span>
+ </div>
+ </div>
+ <div class="form-group row">
+ <label class="cd-col-form-label required"
+ for="zonegroupName"
+ i18n>Rename default zonegroup</label>
+ <div class="cd-col-form-input">
+ <input class="form-control"
+ type="text"
+ placeholder="Zonegroup name..."
+ id="zonegroupName"
+ name="zonegroupName"
+ formControlName="zonegroupName">
+ <span class="invalid-feedback"
+ *ngIf="multisiteMigrateForm.showError('zonegroupName', formDir, 'required')"
+ i18n>This field is required.</span>
+ <span class="invalid-feedback"
+ *ngIf="multisiteMigrateForm.showError('zonegroupName', formDir, 'uniqueName')"
+ i18n>The chosen zonegroup name is already in use.</span>
+ </div>
+ </div>
+ <div class="form-group row">
+ <label class="cd-col-form-label required"
+ for="zonegroup_endpoints"
+ i18n>Zonegroup Endpoints</label>
+ <div class="cd-col-form-input">
+ <input class="form-control"
+ type="text"
+ placeholder="e.g, http://ceph-node-00.com:80"
+ id="zonegroup_endpoints"
+ name="zonegroup_endpoints"
+ formControlName="zonegroup_endpoints">
+ <span class="invalid-feedback"
+ *ngIf="multisiteMigrateForm.showError('zonegroup_endpoints', formDir, 'required')"
+ i18n>This field is required.</span>
+ <span class="invalid-feedback"
+ *ngIf="multisiteMigrateForm.showError('zonegroup_endpoints', formDir, 'endpoint')"
+ i18n>Please enter a valid IP address.</span>
+ </div>
+ </div>
+ <div class="form-group row">
+ <label class="cd-col-form-label required"
+ for="zoneName"
+ i18n>Rename default zone</label>
+ <div class="cd-col-form-input">
+ <input class="form-control"
+ type="text"
+ placeholder="Zone name..."
+ id="zoneName"
+ name="zoneName"
+ formControlName="zoneName">
+ <span class="invalid-feedback"
+ *ngIf="multisiteMigrateForm.showError('zoneName', formDir, 'required')"
+ i18n>This field is required.</span>
+ <span class="invalid-feedback"
+ *ngIf="multisiteMigrateForm.showError('zoneName', formDir, 'uniqueName')"
+ i18n>The chosen zone name is already in use.</span>
+ </div>
+ </div>
+ <div class="form-group row">
+ <label class="cd-col-form-label required"
+ for="zone_endpoints"
+ i18n>Zone Endpoints</label>
+ <div class="cd-col-form-input">
+ <input class="form-control"
+ type="text"
+ placeholder="e.g, http://ceph-node-00.com:80"
+ id="zone_endpoints"
+ name="zone_endpoints"
+ formControlName="zone_endpoints">
+ <span class="invalid-feedback"
+ *ngIf="multisiteMigrateForm.showError('zone_endpoints', formDir, 'required')"
+ i18n>This field is required.</span>
+ <span class="invalid-feedback"
+ *ngIf="multisiteMigrateForm.showError('zone_endpoints', formDir, 'endpoint')"
+ i18n>Please enter a valid IP address.</span>
+ </div>
+ </div>
+ <div class="form-group row">
+ <label class="cd-col-form-label"
+ for="users"
+ i18n>System User</label>
+ <div class="cd-col-form-input">
+ <select id="users"
+ name="users"
+ class="form-select"
+ formControlName="users">
+ <option i18n
+ *ngIf="users === null"
+ [ngValue]="null">Loading...</option>
+ <option i18n
+ *ngIf="users !== null"
+ [ngValue]="null">-- Select a user --</option>
+ <option *ngFor="let user of users"
+ [value]="user.user_id">{{ user.user_id }}</option>
+ </select>
+ </div>
+ </div>
+ </div>
+ <div class="modal-footer">
+ <cd-form-button-panel (submitActionEvent)="submit()"
+ [form]="multisiteMigrateForm"></cd-form-button-panel>
+ </div>
+ </form>
+ </ng-container>
+</cd-modal>
--- /dev/null
+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<RgwMultisiteMigrateComponent>;
+
+ 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();
+ });
+});
--- /dev/null
+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;
+ }
+}
this.onZoneGroupChange(this.info.data.parent);
setTimeout(() => {
this.getUserInfo(zone);
- }, 1500);
+ }, 1000);
}
if (
this.multisiteZoneForm.getValue('selectedZonegroup') !==
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(
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: [
RgwMultisiteZoneFormComponent,
RgwMultisiteZoneDeletionFormComponent,
RgwMultisiteZonegroupDeletionFormComponent,
- RgwSystemUserComponent
+ RgwSystemUserComponent,
+ RgwMultisiteMigrateComponent
]
})
export class RgwModule {}
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'
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);
+ });
+ }
}
RESYNC: string;
EXPORT: string;
IMPORT: any;
+ MIGRATE: string;
constructor() {
/* Create a new item */
this.IMPORT = $localize`Import`;
+ this.MIGRATE = $localize`Migrate to Multi-Site`;
+
/* Destroy an existing item */
this.DELETE = $localize`Delete`;
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):
"""